From ae000aa7cfdc18aaeccea1515b9905b024238091 Mon Sep 17 00:00:00 2001 From: Jacob Lee Date: Mon, 12 Aug 2024 15:20:35 -0700 Subject: [PATCH] Adds docstrings to more models (#6510) --- .../integrations/chat/google_vertex_ai.ipynb | 5 +- libs/langchain-anthropic/src/chat_models.ts | 10 +- .../src/chat_models/fireworks.ts | 418 +++++++++++++++++- .../src/chat_models.ts | 285 +++++++++++- .../src/chat_models.ts | 282 +++++++++++- libs/langchain-groq/src/chat_models.ts | 327 +++++++++++++- 6 files changed, 1298 insertions(+), 29 deletions(-) diff --git a/docs/core_docs/docs/integrations/chat/google_vertex_ai.ipynb b/docs/core_docs/docs/integrations/chat/google_vertex_ai.ipynb index 16f236349335..f48211412ed6 100644 --- a/docs/core_docs/docs/integrations/chat/google_vertex_ai.ipynb +++ b/docs/core_docs/docs/integrations/chat/google_vertex_ai.ipynb @@ -117,9 +117,8 @@ " model: \"gemini-1.5-pro\",\n", " temperature: 0,\n", " maxRetries: 2,\n", - " authOptions: {\n", - " // ... auth options\n", - " }\n", + " // For web, authOptions.credentials\n", + " // authOptions: { ... }\n", " // other params...\n", "})" ] diff --git a/libs/langchain-anthropic/src/chat_models.ts b/libs/langchain-anthropic/src/chat_models.ts index cc8573d11f61..11d683cba8cc 100644 --- a/libs/langchain-anthropic/src/chat_models.ts +++ b/libs/langchain-anthropic/src/chat_models.ts @@ -126,13 +126,13 @@ export interface AnthropicInput { /** Anthropic API URL */ anthropicApiUrl?: string; + /** @deprecated Use "model" instead */ + modelName?: string; /** Model name to use */ - modelName: string; - /** Model name to use */ - model: string; + model?: string; /** Overridable Anthropic ClientOptions */ - clientOptions: ClientOptions; + clientOptions?: ClientOptions; /** Holds any additional parameters that are valid to pass to {@link * https://console.anthropic.com/docs/api/reference | @@ -611,7 +611,7 @@ export class ChatAnthropicMessages< streamUsage = true; - constructor(fields?: Partial & BaseChatModelParams) { + constructor(fields?: AnthropicInput & BaseChatModelParams) { super(fields ?? {}); this.anthropicApiKey = diff --git a/libs/langchain-community/src/chat_models/fireworks.ts b/libs/langchain-community/src/chat_models/fireworks.ts index bd93efdf800a..f6bf28824258 100644 --- a/libs/langchain-community/src/chat_models/fireworks.ts +++ b/libs/langchain-community/src/chat_models/fireworks.ts @@ -30,18 +30,420 @@ export type ChatFireworksCallOptions = Partial< * Fireworks API is compatible to the OpenAI API with some limitations described in * https://readme.fireworks.ai/docs/openai-compatibility. * - * To use, you should have the `openai` package installed and - * the `FIREWORKS_API_KEY` environment variable set. - * @example + * To use, you should have the `FIREWORKS_API_KEY` environment variable set. + * + * Setup: + * Install `@langchain/community` and set a environment variable called `FIREWORKS_API_KEY`. + * + * ```bash + * npm install @langchain/community + * export FIREWORKS_API_KEY="your-api-key" + * ``` + * + * ## [Constructor args](https://api.js.langchain.com/classes/langchain_community_chat_models_fireworks.ChatFireworks.html#constructor) + * + * ## [Runtime args](https://api.js.langchain.com/interfaces/langchain_openai.ChatOpenAICallOptions.html) + * + * Because the Fireworks API extends OpenAI's, the call option type is the same. + * + * Runtime args can be passed as the second argument to any of the base runnable methods `.invoke`. `.stream`, `.batch`, etc. + * They can also be passed via `.bind`, or the second arg in `.bindTools`, like shown in the examples below: + * * ```typescript - * const model = new ChatFireworks({ - * temperature: 0.9, - * apiKey: "YOUR-API-KEY", + * // When calling `.bind`, call options should be passed via the first argument + * const llmWithArgsBound = llm.bind({ + * stop: ["\n"], + * tools: [...], * }); * - * const response = await model.invoke("Hello, how are you?"); - * console.log(response); + * // When calling `.bindTools`, call options should be passed via the second argument + * const llmWithTools = llm.bindTools( + * [...], + * { + * stop: ["\n"], + * } + * ); * ``` + * + * ## Examples + * + *
+ * Instantiate + * + * ```typescript + * import { ChatFireworks } from '@langchain/community/chat_models/fireworks'; + * + * const llm = new ChatFireworks({ + * model: "command-r-plus", + * temperature: 0, + * // other params... + * }); + * ``` + *
+ * + *
+ * + *
+ * Invoking + * + * ```typescript + * const input = `Translate "I love programming" into French.`; + * + * // Models also accept a list of chat messages or a formatted prompt + * const result = await llm.invoke(input); + * console.log(result); + * ``` + * + * ```txt + * AIMessage { + * "id": "dbc233df-532e-4aaa-8995-9d6ea65fea15", + * "content": "The translation of \"I love programming\" into French is:\n\n\"J'adore la programmation.\"\n\nHere's a breakdown of the translation:\n\n* \"I\" is translated to \"Je\" (but in informal writing, it's common to use \"J'\" instead of \"Je\" when it's followed by a vowel)\n* \"love\" is translated to \"adore\"\n* \"programming\" is translated to \"la programmation\"\n\nSo, the complete translation is \"J'adore la programmation.\"", + * "additional_kwargs": {}, + * "response_metadata": { + * "tokenUsage": { + * "completionTokens": 105, + * "promptTokens": 19, + * "totalTokens": 124 + * }, + * "finish_reason": "stop" + * }, + * "tool_calls": [], + * "invalid_tool_calls": [], + * "usage_metadata": { + * "input_tokens": 19, + * "output_tokens": 105, + * "total_tokens": 124 + * } + * } + * ``` + *
+ * + *
+ * + *
+ * Streaming Chunks + * + * ```typescript + * for await (const chunk of await llm.stream(input)) { + * console.log(chunk); + * } + * ``` + * + * ```txt + * AIMessageChunk { + * "id": "ed5fc403-b7ed-4447-819f-f9645ea0277c", + * "content": "", + * "additional_kwargs": {}, + * "response_metadata": { + * "prompt": 0, + * "completion": 0, + * "finish_reason": null + * }, + * "tool_calls": [], + * "tool_call_chunks": [], + * "invalid_tool_calls": [] + * } + * AIMessageChunk { + * "id": "ed5fc403-b7ed-4447-819f-f9645ea0277c", + * "content": "The translation", + * "additional_kwargs": {}, + * "response_metadata": { + * "prompt": 0, + * "completion": 0, + * "finish_reason": null + * }, + * "tool_calls": [], + * "tool_call_chunks": [], + * "invalid_tool_calls": [] + * } + * AIMessageChunk { + * "id": "ed5fc403-b7ed-4447-819f-f9645ea0277c", + * "content": " of \"", + * "additional_kwargs": {}, + * "response_metadata": { + * "prompt": 0, + * "completion": 0, + * "finish_reason": null + * }, + * "tool_calls": [], + * "tool_call_chunks": [], + * "invalid_tool_calls": [] + * } + * AIMessageChunk { + * "id": "ed5fc403-b7ed-4447-819f-f9645ea0277c", + * "content": "I love", + * "additional_kwargs": {}, + * "response_metadata": { + * "prompt": 0, + * "completion": 0, + * "finish_reason": null + * }, + * "tool_calls": [], + * "tool_call_chunks": [], + * "invalid_tool_calls": [] + * } + * AIMessageChunk { + * "id": "ed5fc403-b7ed-4447-819f-f9645ea0277c", + * "content": " programming\"", + * "additional_kwargs": {}, + * "response_metadata": { + * "prompt": 0, + * "completion": 0, + * "finish_reason": null + * }, + * "tool_calls": [], + * "tool_call_chunks": [], + * "invalid_tool_calls": [] + * } + * AIMessageChunk { + * "id": "ed5fc403-b7ed-4447-819f-f9645ea0277c", + * "content": " into French", + * "additional_kwargs": {}, + * "response_metadata": { + * "prompt": 0, + * "completion": 0, + * "finish_reason": null + * }, + * "tool_calls": [], + * "tool_call_chunks": [], + * "invalid_tool_calls": [] + * } + * AIMessageChunk { + * "id": "ed5fc403-b7ed-4447-819f-f9645ea0277c", + * "content": " is:\n\n", + * "additional_kwargs": {}, + * "response_metadata": { + * "prompt": 0, + * "completion": 0, + * "finish_reason": null + * }, + * "tool_calls": [], + * "tool_call_chunks": [], + * "invalid_tool_calls": [] + * } + * AIMessageChunk { + * "id": "ed5fc403-b7ed-4447-819f-f9645ea0277c", + * "content": "\"J", + * "additional_kwargs": {}, + * "response_metadata": { + * "prompt": 0, + * "completion": 0, + * "finish_reason": null + * }, + * "tool_calls": [], + * "tool_call_chunks": [], + * "invalid_tool_calls": [] + * } + * ... + * AIMessageChunk { + * "id": "ed5fc403-b7ed-4447-819f-f9645ea0277c", + * "content": "ation.\"", + * "additional_kwargs": {}, + * "response_metadata": { + * "prompt": 0, + * "completion": 0, + * "finish_reason": null + * }, + * "tool_calls": [], + * "tool_call_chunks": [], + * "invalid_tool_calls": [] + * } + * AIMessageChunk { + * "id": "ed5fc403-b7ed-4447-819f-f9645ea0277c", + * "content": "", + * "additional_kwargs": {}, + * "response_metadata": { + * "prompt": 0, + * "completion": 0, + * "finish_reason": "stop" + * }, + * "tool_calls": [], + * "tool_call_chunks": [], + * "invalid_tool_calls": [] + * } + * AIMessageChunk { + * "content": "", + * "additional_kwargs": {}, + * "response_metadata": {}, + * "tool_calls": [], + * "tool_call_chunks": [], + * "invalid_tool_calls": [], + * "usage_metadata": { + * "input_tokens": 19, + * "output_tokens": 105, + * "total_tokens": 124 + * } + * } + * ``` + *
+ * + *
+ * + *
+ * Aggregate Streamed Chunks + * + * ```typescript + * import { AIMessageChunk } from '@langchain/core/messages'; + * import { concat } from '@langchain/core/utils/stream'; + * + * const stream = await llm.stream(input); + * let full: AIMessageChunk | undefined; + * for await (const chunk of stream) { + * full = !full ? chunk : concat(full, chunk); + * } + * console.log(full); + * ``` + * + * ```txt + * AIMessageChunk { + * "id": "9b80e5af-0f50-4fb7-b700-6d431a819556", + * "content": "The translation of \"I love programming\" into French is:\n\n\"J'adore la programmation.\"\n\nHere's a breakdown of the translation:\n\n* \"I\" is translated to \"Je\" (but in informal writing, it's common to use \"J'\" instead of \"Je\" when it's followed by a vowel)\n* \"love\" is translated to \"adore\"\n* \"programming\" is translated to \"la programmation\"\n\nSo, the complete translation is \"J'adore la programmation.\"", + * "additional_kwargs": {}, + * "response_metadata": { + * "prompt": 0, + * "completion": 0, + * "finish_reason": "stop" + * }, + * "tool_calls": [], + * "tool_call_chunks": [], + * "invalid_tool_calls": [], + * "usage_metadata": { + * "input_tokens": 19, + * "output_tokens": 105, + * "total_tokens": 124 + * } + * } + * ``` + *
+ * + *
+ * + *
+ * Bind tools + * + * ```typescript + * import { z } from 'zod'; + * + * const llmForToolCalling = new ChatFireworks({ + * // Use a model with tool calling capability + * model: "accounts/fireworks/models/firefunction-v2", + * temperature: 0, + * // other params... + * }); + * const GetWeather = { + * name: "GetWeather", + * description: "Get the current weather in a given location", + * schema: z.object({ + * location: z.string().describe("The city and state, e.g. San Francisco, CA") + * }), + * } + * + * const GetPopulation = { + * name: "GetPopulation", + * description: "Get the current population in a given location", + * schema: z.object({ + * location: z.string().describe("The city and state, e.g. San Francisco, CA") + * }), + * } + * + * const llmWithTools = llmForToolCalling.bindTools([GetWeather, GetPopulation]); + * const aiMsg = await llmWithTools.invoke( + * "Which city is hotter today and which is bigger: LA or NY?" + * ); + * console.log(aiMsg.tool_calls); + * ``` + * + * ```txt + * [ + * { + * name: 'GetWeather', + * args: { location: 'Los Angeles, CA' }, + * type: 'tool_call', + * id: 'call_9DE0WnhgKDbxu6HyHOkDQFub' + * }, + * { + * name: 'GetWeather', + * args: { location: 'New York, NY' }, + * type: 'tool_call', + * id: 'call_58lcAPTqQyiqepxynwARhGs8' + * }, + * { + * name: 'GetPopulation', + * args: { location: 'Los Angeles, CA' }, + * type: 'tool_call', + * id: 'call_r0m6AFoqaMvPp4Zt5aEAc0oE' + * }, + * { + * name: 'GetPopulation', + * args: { location: 'New York, NY' }, + * type: 'tool_call', + * id: 'call_mENaPG1ryOF44BmaW4VkBaSi' + * } + * ] + * ``` + *
+ * + *
+ * + *
+ * Structured Output + * + * ```typescript + * import { z } from 'zod'; + * + * const Joke = z.object({ + * setup: z.string().describe("The setup of the joke"), + * punchline: z.string().describe("The punchline to the joke"), + * rating: z.number().optional().describe("How funny the joke is, from 1 to 10") + * }).describe('Joke to tell user.'); + * + * const structuredLlm = llmForToolCalling.withStructuredOutput(Joke, { name: "Joke" }); + * const jokeResult = await structuredLlm.invoke("Tell me a joke about cats"); + * console.log(jokeResult); + * ``` + * + * ```txt + * { + * setup: 'Why did the cat join a band?', + * punchline: 'Because it wanted to be the purr-cussionist!', + * rating: 8 + * } + * ``` + *
+ * + *
+ * + * Usage Metadata + * + * ```typescript + * const aiMsgForMetadata = await llm.invoke(input); + * console.log(aiMsgForMetadata.usage_metadata); + * ``` + * + * ```txt + * { input_tokens: 277, output_tokens: 8, total_tokens: 285 } + * ``` + * + * + *
+ * + *
+ * Response Metadata + * + * ```typescript + * const aiMsgForResponseMetadata = await llm.invoke(input); + * console.log(aiMsgForResponseMetadata.response_metadata); + * ``` + * + * ```txt + * { + * tokenUsage: { completionTokens: 8, promptTokens: 277, totalTokens: 285 }, + * finish_reason: 'stop' + * } + * ``` + *
+ * + *
*/ export class ChatFireworks extends ChatOpenAI { static lc_name() { diff --git a/libs/langchain-google-vertexai-web/src/chat_models.ts b/libs/langchain-google-vertexai-web/src/chat_models.ts index ca6914b70e70..4d8f42de719d 100644 --- a/libs/langchain-google-vertexai-web/src/chat_models.ts +++ b/libs/langchain-google-vertexai-web/src/chat_models.ts @@ -6,8 +6,289 @@ import { type ChatGoogleInput, ChatGoogle } from "@langchain/google-webauth"; export interface ChatVertexAIInput extends ChatGoogleInput {} /** - * Integration with a Google Vertex AI chat model using - * the "@langchain/google-webauth" package for auth. + * Integration with Google Vertex AI chat models in web environments. + * + * Setup: + * Install `@langchain/google-vertexai-web` and set your stringified + * Vertex AI credentials as an environment variable named `GOOGLE_VERTEX_AI_WEB_CREDENTIALS`. + * + * ```bash + * npm install @langchain/google-vertexai-web + * export GOOGLE_VERTEX_AI_WEB_CREDENTIALS={"type":"service_account","project_id":"YOUR_PROJECT-12345",...} + * ``` + * + * ## [Constructor args](https://api.js.langchain.com/classes/langchain_community_chat_models_googlevertexai_web.ChatGoogleVertexAI.html#constructor) + * + * ## [Runtime args](https://api.js.langchain.com/interfaces/langchain_google_common_types.GoogleAIBaseLanguageModelCallOptions.html) + * + * Runtime args can be passed as the second argument to any of the base runnable methods `.invoke`. `.stream`, `.batch`, etc. + * They can also be passed via `.bind`, or the second arg in `.bindTools`, like shown in the examples below: + * + * ```typescript + * // When calling `.bind`, call options should be passed via the first argument + * const llmWithArgsBound = llm.bind({ + * stop: ["\n"], + * tools: [...], + * }); + * + * // When calling `.bindTools`, call options should be passed via the second argument + * const llmWithTools = llm.bindTools( + * [...], + * { + * tool_choice: "auto", + * } + * ); + * ``` + * + * ## Examples + * + *
+ * Instantiate + * + * ```typescript + * import { ChatVertexAI } from '@langchain/google-vertexai-web'; + * + * const llm = new ChatVertexAI({ + * model: "gemini-1.5-pro", + * temperature: 0, + * authOptions: { + * credentials: process.env.GOOGLE_VERTEX_AI_WEB_CREDENTIALS, + * }, + * // other params... + * }); + * ``` + *
+ * + *
+ * + *
+ * Invoking + * + * ```typescript + * const input = `Translate "I love programming" into French.`; + * + * // Models also accept a list of chat messages or a formatted prompt + * const result = await llm.invoke(input); + * console.log(result); + * ``` + * + * ```txt + * AIMessageChunk { + * "content": "\"J'adore programmer\" \n\nHere's why this is the best translation:\n\n* **J'adore** means \"I love\" and conveys a strong passion.\n* **Programmer** is the French verb for \"to program.\"\n\nThis translation is natural and idiomatic in French. \n", + * "additional_kwargs": {}, + * "response_metadata": {}, + * "tool_calls": [], + * "tool_call_chunks": [], + * "invalid_tool_calls": [], + * "usage_metadata": { + * "input_tokens": 9, + * "output_tokens": 63, + * "total_tokens": 72 + * } + * } + * ``` + *
+ * + *
+ * + *
+ * Streaming Chunks + * + * ```typescript + * for await (const chunk of await llm.stream(input)) { + * console.log(chunk); + * } + * ``` + * + * ```txt + * AIMessageChunk { + * "content": "\"", + * "additional_kwargs": {}, + * "response_metadata": {}, + * "tool_calls": [], + * "tool_call_chunks": [], + * "invalid_tool_calls": [] + * } + * AIMessageChunk { + * "content": "J'adore programmer\" \n", + * "additional_kwargs": {}, + * "response_metadata": {}, + * "tool_calls": [], + * "tool_call_chunks": [], + * "invalid_tool_calls": [] + * } + * AIMessageChunk { + * "content": "", + * "additional_kwargs": {}, + * "response_metadata": {}, + * "tool_calls": [], + * "tool_call_chunks": [], + * "invalid_tool_calls": [] + * } + * AIMessageChunk { + * "content": "", + * "additional_kwargs": {}, + * "response_metadata": { + * "finishReason": "stop" + * }, + * "tool_calls": [], + * "tool_call_chunks": [], + * "invalid_tool_calls": [], + * "usage_metadata": { + * "input_tokens": 9, + * "output_tokens": 8, + * "total_tokens": 17 + * } + * } + * ``` + *
+ * + *
+ * + *
+ * Aggregate Streamed Chunks + * + * ```typescript + * import { AIMessageChunk } from '@langchain/core/messages'; + * import { concat } from '@langchain/core/utils/stream'; + * + * const stream = await llm.stream(input); + * let full: AIMessageChunk | undefined; + * for await (const chunk of stream) { + * full = !full ? chunk : concat(full, chunk); + * } + * console.log(full); + * ``` + * + * ```txt + * AIMessageChunk { + * "content": "\"J'adore programmer\" \n", + * "additional_kwargs": {}, + * "response_metadata": { + * "finishReason": "stop" + * }, + * "tool_calls": [], + * "tool_call_chunks": [], + * "invalid_tool_calls": [], + * "usage_metadata": { + * "input_tokens": 9, + * "output_tokens": 8, + * "total_tokens": 17 + * } + * } + * ``` + *
+ * + *
+ * + *
+ * Bind tools + * + * ```typescript + * import { z } from 'zod'; + * + * const GetWeather = { + * name: "GetWeather", + * description: "Get the current weather in a given location", + * schema: z.object({ + * location: z.string().describe("The city and state, e.g. San Francisco, CA") + * }), + * } + * + * const GetPopulation = { + * name: "GetPopulation", + * description: "Get the current population in a given location", + * schema: z.object({ + * location: z.string().describe("The city and state, e.g. San Francisco, CA") + * }), + * } + * + * const llmWithTools = llm.bindTools([GetWeather, GetPopulation]); + * const aiMsg = await llmWithTools.invoke( + * "Which city is hotter today and which is bigger: LA or NY?" + * ); + * console.log(aiMsg.tool_calls); + * ``` + * + * ```txt + * [ + * { + * name: 'GetPopulation', + * args: { location: 'New York City, NY' }, + * id: '33c1c1f47e2f492799c77d2800a43912', + * type: 'tool_call' + * } + * ] + * ``` + *
+ * + *
+ * + *
+ * Structured Output + * + * ```typescript + * import { z } from 'zod'; + * + * const Joke = z.object({ + * setup: z.string().describe("The setup of the joke"), + * punchline: z.string().describe("The punchline to the joke"), + * rating: z.number().optional().describe("How funny the joke is, from 1 to 10") + * }).describe('Joke to tell user.'); + * + * const structuredLlm = llm.withStructuredOutput(Joke, { name: "Joke" }); + * const jokeResult = await structuredLlm.invoke("Tell me a joke about cats"); + * console.log(jokeResult); + * ``` + * + * ```txt + * { + * setup: 'What do you call a cat that loves to bowl?', + * punchline: 'An alley cat!' + * } + * ``` + *
+ * + *
+ * + *
+ * Usage Metadata + * + * ```typescript + * const aiMsgForMetadata = await llm.invoke(input); + * console.log(aiMsgForMetadata.usage_metadata); + * ``` + * + * ```txt + * { input_tokens: 9, output_tokens: 8, total_tokens: 17 } + * ``` + *
+ * + *
+ * + *
+ * Stream Usage Metadata + * + * ```typescript + * const streamForMetadata = await llm.stream( + * input, + * { + * streamUsage: true + * } + * ); + * let fullForMetadata: AIMessageChunk | undefined; + * for await (const chunk of streamForMetadata) { + * fullForMetadata = !fullForMetadata ? chunk : concat(fullForMetadata, chunk); + * } + * console.log(fullForMetadata?.usage_metadata); + * ``` + * + * ```txt + * { input_tokens: 9, output_tokens: 8, total_tokens: 17 } + * ``` + *
+ * + *
*/ export class ChatVertexAI extends ChatGoogle { static lc_name() { diff --git a/libs/langchain-google-vertexai/src/chat_models.ts b/libs/langchain-google-vertexai/src/chat_models.ts index 65ad408c8098..1f5ae73ec8f4 100644 --- a/libs/langchain-google-vertexai/src/chat_models.ts +++ b/libs/langchain-google-vertexai/src/chat_models.ts @@ -6,8 +6,286 @@ import { type ChatGoogleInput, ChatGoogle } from "@langchain/google-gauth"; export interface ChatVertexAIInput extends ChatGoogleInput {} /** - * Integration with a Google Vertex AI chat model using - * the "@langchain/google-gauth" package for auth. + * Integration with Google Vertex AI chat models. + * + * Setup: + * Install `@langchain/google-vertexai` and set your stringified + * Vertex AI credentials as an environment variable named `GOOGLE_APPLICATION_CREDENTIALS`. + * + * ```bash + * npm install @langchain/google-vertexai + * export GOOGLE_APPLICATION_CREDENTIALS="path/to/credentials" + * ``` + * + * ## [Constructor args](https://api.js.langchain.com/classes/langchain_community_chat_models_googlevertexai_web.ChatGoogleVertexAI.html#constructor) + * + * ## [Runtime args](https://api.js.langchain.com/interfaces/langchain_google_common_types.GoogleAIBaseLanguageModelCallOptions.html) + * + * Runtime args can be passed as the second argument to any of the base runnable methods `.invoke`. `.stream`, `.batch`, etc. + * They can also be passed via `.bind`, or the second arg in `.bindTools`, like shown in the examples below: + * + * ```typescript + * // When calling `.bind`, call options should be passed via the first argument + * const llmWithArgsBound = llm.bind({ + * stop: ["\n"], + * tools: [...], + * }); + * + * // When calling `.bindTools`, call options should be passed via the second argument + * const llmWithTools = llm.bindTools( + * [...], + * { + * tool_choice: "auto", + * } + * ); + * ``` + * + * ## Examples + * + *
+ * Instantiate + * + * ```typescript + * import { ChatVertexAI } from '@langchain/google-vertexai'; + * + * const llm = new ChatVertexAI({ + * model: "gemini-1.5-pro", + * temperature: 0, + * // other params... + * }); + * ``` + *
+ * + *
+ * + *
+ * Invoking + * + * ```typescript + * const input = `Translate "I love programming" into French.`; + * + * // Models also accept a list of chat messages or a formatted prompt + * const result = await llm.invoke(input); + * console.log(result); + * ``` + * + * ```txt + * AIMessageChunk { + * "content": "\"J'adore programmer\" \n\nHere's why this is the best translation:\n\n* **J'adore** means \"I love\" and conveys a strong passion.\n* **Programmer** is the French verb for \"to program.\"\n\nThis translation is natural and idiomatic in French. \n", + * "additional_kwargs": {}, + * "response_metadata": {}, + * "tool_calls": [], + * "tool_call_chunks": [], + * "invalid_tool_calls": [], + * "usage_metadata": { + * "input_tokens": 9, + * "output_tokens": 63, + * "total_tokens": 72 + * } + * } + * ``` + *
+ * + *
+ * + *
+ * Streaming Chunks + * + * ```typescript + * for await (const chunk of await llm.stream(input)) { + * console.log(chunk); + * } + * ``` + * + * ```txt + * AIMessageChunk { + * "content": "\"", + * "additional_kwargs": {}, + * "response_metadata": {}, + * "tool_calls": [], + * "tool_call_chunks": [], + * "invalid_tool_calls": [] + * } + * AIMessageChunk { + * "content": "J'adore programmer\" \n", + * "additional_kwargs": {}, + * "response_metadata": {}, + * "tool_calls": [], + * "tool_call_chunks": [], + * "invalid_tool_calls": [] + * } + * AIMessageChunk { + * "content": "", + * "additional_kwargs": {}, + * "response_metadata": {}, + * "tool_calls": [], + * "tool_call_chunks": [], + * "invalid_tool_calls": [] + * } + * AIMessageChunk { + * "content": "", + * "additional_kwargs": {}, + * "response_metadata": { + * "finishReason": "stop" + * }, + * "tool_calls": [], + * "tool_call_chunks": [], + * "invalid_tool_calls": [], + * "usage_metadata": { + * "input_tokens": 9, + * "output_tokens": 8, + * "total_tokens": 17 + * } + * } + * ``` + *
+ * + *
+ * + *
+ * Aggregate Streamed Chunks + * + * ```typescript + * import { AIMessageChunk } from '@langchain/core/messages'; + * import { concat } from '@langchain/core/utils/stream'; + * + * const stream = await llm.stream(input); + * let full: AIMessageChunk | undefined; + * for await (const chunk of stream) { + * full = !full ? chunk : concat(full, chunk); + * } + * console.log(full); + * ``` + * + * ```txt + * AIMessageChunk { + * "content": "\"J'adore programmer\" \n", + * "additional_kwargs": {}, + * "response_metadata": { + * "finishReason": "stop" + * }, + * "tool_calls": [], + * "tool_call_chunks": [], + * "invalid_tool_calls": [], + * "usage_metadata": { + * "input_tokens": 9, + * "output_tokens": 8, + * "total_tokens": 17 + * } + * } + * ``` + *
+ * + *
+ * + *
+ * Bind tools + * + * ```typescript + * import { z } from 'zod'; + * + * const GetWeather = { + * name: "GetWeather", + * description: "Get the current weather in a given location", + * schema: z.object({ + * location: z.string().describe("The city and state, e.g. San Francisco, CA") + * }), + * } + * + * const GetPopulation = { + * name: "GetPopulation", + * description: "Get the current population in a given location", + * schema: z.object({ + * location: z.string().describe("The city and state, e.g. San Francisco, CA") + * }), + * } + * + * const llmWithTools = llm.bindTools([GetWeather, GetPopulation]); + * const aiMsg = await llmWithTools.invoke( + * "Which city is hotter today and which is bigger: LA or NY?" + * ); + * console.log(aiMsg.tool_calls); + * ``` + * + * ```txt + * [ + * { + * name: 'GetPopulation', + * args: { location: 'New York City, NY' }, + * id: '33c1c1f47e2f492799c77d2800a43912', + * type: 'tool_call' + * } + * ] + * ``` + *
+ * + *
+ * + *
+ * Structured Output + * + * ```typescript + * import { z } from 'zod'; + * + * const Joke = z.object({ + * setup: z.string().describe("The setup of the joke"), + * punchline: z.string().describe("The punchline to the joke"), + * rating: z.number().optional().describe("How funny the joke is, from 1 to 10") + * }).describe('Joke to tell user.'); + * + * const structuredLlm = llm.withStructuredOutput(Joke, { name: "Joke" }); + * const jokeResult = await structuredLlm.invoke("Tell me a joke about cats"); + * console.log(jokeResult); + * ``` + * + * ```txt + * { + * setup: 'What do you call a cat that loves to bowl?', + * punchline: 'An alley cat!' + * } + * ``` + *
+ * + *
+ * + *
+ * Usage Metadata + * + * ```typescript + * const aiMsgForMetadata = await llm.invoke(input); + * console.log(aiMsgForMetadata.usage_metadata); + * ``` + * + * ```txt + * { input_tokens: 9, output_tokens: 8, total_tokens: 17 } + * ``` + *
+ * + *
+ * + *
+ * Stream Usage Metadata + * + * ```typescript + * const streamForMetadata = await llm.stream( + * input, + * { + * streamUsage: true + * } + * ); + * let fullForMetadata: AIMessageChunk | undefined; + * for await (const chunk of streamForMetadata) { + * fullForMetadata = !fullForMetadata ? chunk : concat(fullForMetadata, chunk); + * } + * console.log(fullForMetadata?.usage_metadata); + * ``` + * + * ```txt + * { input_tokens: 9, output_tokens: 8, total_tokens: 17 } + * ``` + *
+ * + *
*/ export class ChatVertexAI extends ChatGoogle { static lc_name() { diff --git a/libs/langchain-groq/src/chat_models.ts b/libs/langchain-groq/src/chat_models.ts index ba05ae9e3c43..823dd41c98f2 100644 --- a/libs/langchain-groq/src/chat_models.ts +++ b/libs/langchain-groq/src/chat_models.ts @@ -292,23 +292,332 @@ function _convertDeltaToMessageChunk( } /** - * Wrapper around Groq API for large language models fine-tuned for chat + * Groq chat model integration. * - * Groq API is compatible to the OpenAI API with some limitations. View the + * The Groq API is compatible to the OpenAI API with some limitations. View the * full API ref at: * @link {https://docs.api.groq.com/md/openai.oas.html} * - * To use, you should have the `GROQ_API_KEY` environment variable set. - * @example + * Setup: + * Install `@langchain/groq` and set an environment variable named `GROQ_API_KEY`. + * + * ```bash + * npm install @langchain/groq + * export GROQ_API_KEY="your-api-key" + * ``` + * + * ## [Constructor args](https://api.js.langchain.com/classes/langchain_groq.ChatGroq.html#constructor) + * + * ## [Runtime args](https://api.js.langchain.com/interfaces/langchain_groq.ChatGroqCallOptions.html) + * + * Runtime args can be passed as the second argument to any of the base runnable methods `.invoke`. `.stream`, `.batch`, etc. + * They can also be passed via `.bind`, or the second arg in `.bindTools`, like shown in the examples below: + * + * ```typescript + * // When calling `.bind`, call options should be passed via the first argument + * const llmWithArgsBound = llm.bind({ + * stop: ["\n"], + * tools: [...], + * }); + * + * // When calling `.bindTools`, call options should be passed via the second argument + * const llmWithTools = llm.bindTools( + * [...], + * { + * tool_choice: "auto", + * } + * ); + * ``` + * + * ## Examples + * + *
+ * Instantiate + * + * ```typescript + * import { ChatGroq } from '@langchain/groq'; + * + * const llm = new ChatGroq({ + * model: "mixtral-8x7b-32768", + * temperature: 0, + * // other params... + * }); + * ``` + *
+ * + *
+ * + *
+ * Invoking + * + * ```typescript + * const input = `Translate "I love programming" into French.`; + * + * // Models also accept a list of chat messages or a formatted prompt + * const result = await llm.invoke(input); + * console.log(result); + * ``` + * + * ```txt + * AIMessage { + * "content": "The French translation of \"I love programming\" is \"J'aime programmer\". In this sentence, \"J'aime\" is the first person singular conjugation of the French verb \"aimer\" which means \"to love\", and \"programmer\" is the French infinitive for \"to program\". I hope this helps! Let me know if you have any other questions.", + * "additional_kwargs": {}, + * "response_metadata": { + * "tokenUsage": { + * "completionTokens": 82, + * "promptTokens": 20, + * "totalTokens": 102 + * }, + * "finish_reason": "stop" + * }, + * "tool_calls": [], + * "invalid_tool_calls": [] + * } + * ``` + *
+ * + *
+ * + *
+ * Streaming Chunks + * + * ```typescript + * for await (const chunk of await llm.stream(input)) { + * console.log(chunk); + * } + * ``` + * + * ```txt + * AIMessageChunk { + * "content": "", + * "additional_kwargs": {}, + * "response_metadata": { + * "finishReason": null + * }, + * "tool_calls": [], + * "tool_call_chunks": [], + * "invalid_tool_calls": [] + * } + * AIMessageChunk { + * "content": "The", + * "additional_kwargs": {}, + * "response_metadata": { + * "finishReason": null + * }, + * "tool_calls": [], + * "tool_call_chunks": [], + * "invalid_tool_calls": [] + * } + * AIMessageChunk { + * "content": " French", + * "additional_kwargs": {}, + * "response_metadata": { + * "finishReason": null + * }, + * "tool_calls": [], + * "tool_call_chunks": [], + * "invalid_tool_calls": [] + * } + * AIMessageChunk { + * "content": " translation", + * "additional_kwargs": {}, + * "response_metadata": { + * "finishReason": null + * }, + * "tool_calls": [], + * "tool_call_chunks": [], + * "invalid_tool_calls": [] + * } + * AIMessageChunk { + * "content": " of", + * "additional_kwargs": {}, + * "response_metadata": { + * "finishReason": null + * }, + * "tool_calls": [], + * "tool_call_chunks": [], + * "invalid_tool_calls": [] + * } + * AIMessageChunk { + * "content": " \"", + * "additional_kwargs": {}, + * "response_metadata": { + * "finishReason": null + * }, + * "tool_calls": [], + * "tool_call_chunks": [], + * "invalid_tool_calls": [] + * } + * AIMessageChunk { + * "content": "I", + * "additional_kwargs": {}, + * "response_metadata": { + * "finishReason": null + * }, + * "tool_calls": [], + * "tool_call_chunks": [], + * "invalid_tool_calls": [] + * } + * AIMessageChunk { + * "content": " love", + * "additional_kwargs": {}, + * "response_metadata": { + * "finishReason": null + * }, + * "tool_calls": [], + * "tool_call_chunks": [], + * "invalid_tool_calls": [] + * } + * ... + * AIMessageChunk { + * "content": ".", + * "additional_kwargs": {}, + * "response_metadata": { + * "finishReason": null + * }, + * "tool_calls": [], + * "tool_call_chunks": [], + * "invalid_tool_calls": [] + * } + * AIMessageChunk { + * "content": "", + * "additional_kwargs": {}, + * "response_metadata": { + * "finishReason": "stop" + * }, + * "tool_calls": [], + * "tool_call_chunks": [], + * "invalid_tool_calls": [] + * } + * ``` + *
+ * + *
+ * + *
+ * Aggregate Streamed Chunks + * * ```typescript - * const model = new ChatGroq({ - * temperature: 0.9, - * apiKey: process.env.GROQ_API_KEY, + * import { AIMessageChunk } from '@langchain/core/messages'; + * import { concat } from '@langchain/core/utils/stream'; + * + * const stream = await llm.stream(input); + * let full: AIMessageChunk | undefined; + * for await (const chunk of stream) { + * full = !full ? chunk : concat(full, chunk); + * } + * console.log(full); + * ``` + * + * ```txt + * AIMessageChunk { + * "content": "The French translation of \"I love programming\" is \"J'aime programmer\". In this sentence, \"J'aime\" is the first person singular conjugation of the French verb \"aimer\" which means \"to love\", and \"programmer\" is the French infinitive for \"to program\". I hope this helps! Let me know if you have any other questions.", + * "additional_kwargs": {}, + * "response_metadata": { + * "finishReason": "stop" + * }, + * "tool_calls": [], + * "tool_call_chunks": [], + * "invalid_tool_calls": [] + * } + * ``` + *
+ * + *
+ * + *
+ * Bind tools + * + * ```typescript + * import { z } from 'zod'; + * + * const llmForToolCalling = new ChatGroq({ + * model: "llama3-groq-70b-8192-tool-use-preview", + * temperature: 0, + * // other params... * }); * - * const response = await model.invoke([new HumanMessage("Hello there!")]); - * console.log(response); + * const GetWeather = { + * name: "GetWeather", + * description: "Get the current weather in a given location", + * schema: z.object({ + * location: z.string().describe("The city and state, e.g. San Francisco, CA") + * }), + * } + * + * const GetPopulation = { + * name: "GetPopulation", + * description: "Get the current population in a given location", + * schema: z.object({ + * location: z.string().describe("The city and state, e.g. San Francisco, CA") + * }), + * } + * + * const llmWithTools = llmForToolCalling.bindTools([GetWeather, GetPopulation]); + * const aiMsg = await llmWithTools.invoke( + * "Which city is hotter today and which is bigger: LA or NY?" + * ); + * console.log(aiMsg.tool_calls); + * ``` + * + * ```txt + * [ + * { + * name: 'GetWeather', + * args: { location: 'Los Angeles, CA' }, + * type: 'tool_call', + * id: 'call_cd34' + * }, + * { + * name: 'GetWeather', + * args: { location: 'New York, NY' }, + * type: 'tool_call', + * id: 'call_68rf' + * }, + * { + * name: 'GetPopulation', + * args: { location: 'Los Angeles, CA' }, + * type: 'tool_call', + * id: 'call_f81z' + * }, + * { + * name: 'GetPopulation', + * args: { location: 'New York, NY' }, + * type: 'tool_call', + * id: 'call_8byt' + * } + * ] + * ``` + *
+ * + *
+ * + *
+ * Structured Output + * + * ```typescript + * import { z } from 'zod'; + * + * const Joke = z.object({ + * setup: z.string().describe("The setup of the joke"), + * punchline: z.string().describe("The punchline to the joke"), + * rating: z.number().optional().describe("How funny the joke is, from 1 to 10") + * }).describe('Joke to tell user.'); + * + * const structuredLlm = llmForToolCalling.withStructuredOutput(Joke, { name: "Joke" }); + * const jokeResult = await structuredLlm.invoke("Tell me a joke about cats"); + * console.log(jokeResult); * ``` + * + * ```txt + * { + * setup: "Why don't cats play poker in the wild?", + * punchline: 'Because there are too many cheetahs.' + * } + * ``` + *
+ * + *
*/ export class ChatGroq extends BaseChatModel< ChatGroqCallOptions,