From d8fc97d2dcb53df84a0d52430add2fde24ea4c56 Mon Sep 17 00:00:00 2001 From: Jacob Lee Date: Mon, 8 Apr 2024 15:39:37 -0700 Subject: [PATCH 01/15] Make thrown evaluator errors not interrupt dataset flow (#5017) --- langchain/src/smith/runner_utils.ts | 6 +- .../smith/tests/run_on_dataset.int.test.ts | 66 +++++++++++++++++++ 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/langchain/src/smith/runner_utils.ts b/langchain/src/smith/runner_utils.ts index 26c2455c74a2..c6d013438250 100644 --- a/langchain/src/smith/runner_utils.ts +++ b/langchain/src/smith/runner_utils.ts @@ -541,7 +541,7 @@ const applyEvaluators = async ({ for (let i = 0; i < runs.length; i += 1) { const run = runs[i]; const example = examples[i]; - const evaluatorResults = await Promise.all( + const evaluatorResults = await Promise.allSettled( evaluators.map((evaluator) => client.evaluateRun(run, evaluator, { referenceExample: example, @@ -555,7 +555,9 @@ const applyEvaluators = async ({ run?.end_time && run.start_time ? run.end_time - run.start_time : undefined, - feedback: evaluatorResults, + feedback: evaluatorResults.map((evalResult) => + evalResult.status === "fulfilled" ? evalResult.value : evalResult.reason + ), run_id: run.id, }; } diff --git a/langchain/src/smith/tests/run_on_dataset.int.test.ts b/langchain/src/smith/tests/run_on_dataset.int.test.ts index 29ad9f8b80c7..54f8079fbfea 100644 --- a/langchain/src/smith/tests/run_on_dataset.int.test.ts +++ b/langchain/src/smith/tests/run_on_dataset.int.test.ts @@ -251,3 +251,69 @@ test(`Chat model dataset`, async () => { }) ); }); + +test("Thrown errors should not interrupt dataset run", async () => { + async function ragPipeline(_: string): Promise { + throw new Error("I don't know, I am learning from aliens."); + } + + const examples = [ + [ + "When was the Apple Vision Pro released in the US?", + "The Apple Vision Pro was released in the United States on February 2, 2024.", + ], + [ + "What is LangChain?", + "LangChain is an open-source framework for building applications using large language models.", + ], + [ + "Who is the chairman of OpenAI?", + "Bret Taylor is the chairman of the OpenAI", + ], + ]; + + const lsClient = new Client(); + const datasetName = "JS run on dataset integration test"; + let dataset: Dataset; + try { + dataset = await lsClient.readDataset({ datasetName }); + } catch (e) { + dataset = await lsClient.createDataset(datasetName); + await Promise.all( + examples.map(async ([question, answer]) => { + await lsClient.createExample( + { question }, + { answer }, + { datasetId: dataset.id } + ); + }) + ); + } + + // An illustrative custom evaluator example + const dummy = async (_: DynamicRunEvaluatorParams) => { + console.log("RUNNING EVAL"); + throw new Error("Expected error"); + }; + + const evaluation: RunEvalConfig = { + // Custom evaluators can be user-defined RunEvaluator's + // or a compatible function + customEvaluators: [dummy], + }; + + const wrappedRagPipeline = async ({ + question, + }: { + question: string; + }): Promise => { + return ragPipeline(question); + }; + + console.log( + await runOnDataset(wrappedRagPipeline, datasetName, { + evaluationConfig: evaluation, + maxConcurrency: 1, + }) + ); +}); From a2dfb465a9836bb5a2fef74ec4407771fbbcfe78 Mon Sep 17 00:00:00 2001 From: Zan <37948383+zandko@users.noreply.github.com> Date: Tue, 9 Apr 2024 08:30:13 +0800 Subject: [PATCH 02/15] community[minor]: feat: BaiduQianfan embeddings (#4926) * feat: BaiduQianfan embeddings * docs: Update instructions for configuring BAIDU API and Secret keys as env variables * refactor: rename BaiduQianFanEmbeddings to BaiduQianfanEmbeddings for naming consistency * Add entrypoint --------- Co-authored-by: jacoblee93 --- .../text_embedding/baidu_qianfan.mdx | 32 +++ examples/src/embeddings/baidu_qianfan.ts | 7 + libs/langchain-community/.gitignore | 4 + libs/langchain-community/langchain.config.js | 1 + libs/langchain-community/package.json | 13 + .../src/embeddings/baidu_qianfan.ts | 238 ++++++++++++++++++ .../tests/baidu_qianfan.int.test.ts | 34 +++ 7 files changed, 329 insertions(+) create mode 100644 docs/core_docs/docs/integrations/text_embedding/baidu_qianfan.mdx create mode 100644 examples/src/embeddings/baidu_qianfan.ts create mode 100644 libs/langchain-community/src/embeddings/baidu_qianfan.ts create mode 100644 libs/langchain-community/src/embeddings/tests/baidu_qianfan.int.test.ts diff --git a/docs/core_docs/docs/integrations/text_embedding/baidu_qianfan.mdx b/docs/core_docs/docs/integrations/text_embedding/baidu_qianfan.mdx new file mode 100644 index 000000000000..341310c6d9f5 --- /dev/null +++ b/docs/core_docs/docs/integrations/text_embedding/baidu_qianfan.mdx @@ -0,0 +1,32 @@ +--- +sidebar_class_name: node-only +--- + +# Baidu Qianfan + +The `BaiduQianfanEmbeddings` class uses the Baidu Qianfan API to generate embeddings for a given text. + +## Setup + +Official Website: https://cloud.baidu.com/doc/WENXINWORKSHOP/s/alj562vvu + +An API key is required to use this embedding model. You can get one by registering at https://cloud.baidu.com/doc/WENXINWORKSHOP/s/alj562vvu. + +Please set the acquired API key as an environment variable named BAIDU_API_KEY, and set your secret key as an environment variable named BAIDU_SECRET_KEY. + +Then, you'll need to install the [`@langchain/community`](https://www.npmjs.com/package/@langchain/community) package: + +import IntegrationInstallTooltip from "@mdx_components/integration_install_tooltip.mdx"; + + + +```bash npm2yarn +npm install @langchain/community +``` + +## Usage + +import CodeBlock from "@theme/CodeBlock"; +import BaiduQianFanExample from "@examples/embeddings/baidu_qianfan.ts"; + +{BaiduQianFanExample} diff --git a/examples/src/embeddings/baidu_qianfan.ts b/examples/src/embeddings/baidu_qianfan.ts new file mode 100644 index 000000000000..9a85ddc6d7b4 --- /dev/null +++ b/examples/src/embeddings/baidu_qianfan.ts @@ -0,0 +1,7 @@ +import { BaiduQianfanEmbeddings } from "@langchain/community/embeddings/baidu_qianfan"; + +const embeddings = new BaiduQianfanEmbeddings(); +const res = await embeddings.embedQuery( + "What would be a good company name a company that makes colorful socks?" +); +console.log({ res }); diff --git a/libs/langchain-community/.gitignore b/libs/langchain-community/.gitignore index 0b2ed0633985..ea93ab28de1c 100644 --- a/libs/langchain-community/.gitignore +++ b/libs/langchain-community/.gitignore @@ -118,6 +118,10 @@ embeddings/alibaba_tongyi.cjs embeddings/alibaba_tongyi.js embeddings/alibaba_tongyi.d.ts embeddings/alibaba_tongyi.d.cts +embeddings/baidu_qianfan.cjs +embeddings/baidu_qianfan.js +embeddings/baidu_qianfan.d.ts +embeddings/baidu_qianfan.d.cts embeddings/bedrock.cjs embeddings/bedrock.js embeddings/bedrock.d.ts diff --git a/libs/langchain-community/langchain.config.js b/libs/langchain-community/langchain.config.js index 65b01ff2385d..afe5975fd5d1 100644 --- a/libs/langchain-community/langchain.config.js +++ b/libs/langchain-community/langchain.config.js @@ -59,6 +59,7 @@ export const config = { "agents/toolkits/connery": "agents/toolkits/connery/index", // embeddings "embeddings/alibaba_tongyi": "embeddings/alibaba_tongyi", + "embeddings/baidu_qianfan": "embeddings/baidu_qianfan", "embeddings/bedrock": "embeddings/bedrock", "embeddings/cloudflare_workersai": "embeddings/cloudflare_workersai", "embeddings/cohere": "embeddings/cohere", diff --git a/libs/langchain-community/package.json b/libs/langchain-community/package.json index 535a27fba108..303ca810d0a2 100644 --- a/libs/langchain-community/package.json +++ b/libs/langchain-community/package.json @@ -822,6 +822,15 @@ "import": "./embeddings/alibaba_tongyi.js", "require": "./embeddings/alibaba_tongyi.cjs" }, + "./embeddings/baidu_qianfan": { + "types": { + "import": "./embeddings/baidu_qianfan.d.ts", + "require": "./embeddings/baidu_qianfan.d.cts", + "default": "./embeddings/baidu_qianfan.d.ts" + }, + "import": "./embeddings/baidu_qianfan.js", + "require": "./embeddings/baidu_qianfan.cjs" + }, "./embeddings/bedrock": { "types": { "import": "./embeddings/bedrock.d.ts", @@ -2359,6 +2368,10 @@ "embeddings/alibaba_tongyi.js", "embeddings/alibaba_tongyi.d.ts", "embeddings/alibaba_tongyi.d.cts", + "embeddings/baidu_qianfan.cjs", + "embeddings/baidu_qianfan.js", + "embeddings/baidu_qianfan.d.ts", + "embeddings/baidu_qianfan.d.cts", "embeddings/bedrock.cjs", "embeddings/bedrock.js", "embeddings/bedrock.d.ts", diff --git a/libs/langchain-community/src/embeddings/baidu_qianfan.ts b/libs/langchain-community/src/embeddings/baidu_qianfan.ts new file mode 100644 index 000000000000..1c5d74bd83a1 --- /dev/null +++ b/libs/langchain-community/src/embeddings/baidu_qianfan.ts @@ -0,0 +1,238 @@ +import { Embeddings, type EmbeddingsParams } from "@langchain/core/embeddings"; +import { chunkArray } from "@langchain/core/utils/chunk_array"; +import { getEnvironmentVariable } from "@langchain/core/utils/env"; + +export interface BaiduQianfanEmbeddingsParams extends EmbeddingsParams { + /** Model name to use */ + modelName: "embedding-v1" | "bge_large_zh" | "bge-large-en" | "tao-8k"; + + /** + * Timeout to use when making requests to BaiduQianfan. + */ + timeout?: number; + + /** + * The maximum number of characters allowed for embedding in a single request varies by model: + * - Embedding-V1 model: up to 1000 characters + * - bge-large-zh model: up to 2000 characters + * - bge-large-en model: up to 2000 characters + * - tao-8k model: up to 28000 characters + * + * Note: These limits are model-specific and should be adhered to for optimal performance. + */ + batchSize?: number; + + /** + * Whether to strip new lines from the input text. + */ + stripNewLines?: boolean; +} + +interface EmbeddingCreateParams { + input: string[]; +} + +interface EmbeddingResponse { + data: { object: "embedding"; index: number; embedding: number[] }[]; + + usage: { + prompt_tokens: number; + total_tokens: number; + }; + + id: string; +} + +interface EmbeddingErrorResponse { + error_code: number | string; + error_msg: string; +} + +export class BaiduQianfanEmbeddings + extends Embeddings + implements BaiduQianfanEmbeddingsParams +{ + modelName: BaiduQianfanEmbeddingsParams["modelName"] = "embedding-v1"; + + batchSize = 16; + + stripNewLines = true; + + baiduApiKey: string; + + baiduSecretKey: string; + + accessToken: string; + + constructor( + fields?: Partial & { + verbose?: boolean; + baiduApiKey?: string; + baiduSecretKey?: string; + } + ) { + const fieldsWithDefaults = { maxConcurrency: 2, ...fields }; + super(fieldsWithDefaults); + + const baiduApiKey = + fieldsWithDefaults?.baiduApiKey ?? + getEnvironmentVariable("BAIDU_API_KEY"); + + const baiduSecretKey = + fieldsWithDefaults?.baiduSecretKey ?? + getEnvironmentVariable("BAIDU_SECRET_KEY"); + + if (!baiduApiKey) { + throw new Error("Baidu API key not found"); + } + + if (!baiduSecretKey) { + throw new Error("Baidu Secret key not found"); + } + + this.baiduApiKey = baiduApiKey; + this.baiduSecretKey = baiduSecretKey; + + this.modelName = fieldsWithDefaults?.modelName ?? this.modelName; + + if (this.modelName === "tao-8k") { + if (fieldsWithDefaults?.batchSize && fieldsWithDefaults.batchSize !== 1) { + throw new Error( + "tao-8k model supports only a batchSize of 1. Please adjust your batchSize accordingly" + ); + } + this.batchSize = 1; + } else { + this.batchSize = fieldsWithDefaults?.batchSize ?? this.batchSize; + } + + this.stripNewLines = + fieldsWithDefaults?.stripNewLines ?? this.stripNewLines; + } + + /** + * Method to generate embeddings for an array of documents. Splits the + * documents into batches and makes requests to the BaiduQianFan API to generate + * embeddings. + * @param texts Array of documents to generate embeddings for. + * @returns Promise that resolves to a 2D array of embeddings for each document. + */ + async embedDocuments(texts: string[]): Promise { + const batches = chunkArray( + this.stripNewLines ? texts.map((t) => t.replace(/\n/g, " ")) : texts, + this.batchSize + ); + + const batchRequests = batches.map((batch) => { + const params = this.getParams(batch); + + return this.embeddingWithRetry(params); + }); + + const batchResponses = await Promise.all(batchRequests); + + const embeddings: number[][] = []; + + for (let i = 0; i < batchResponses.length; i += 1) { + const batch = batches[i]; + const batchResponse = batchResponses[i] || []; + for (let j = 0; j < batch.length; j += 1) { + embeddings.push(batchResponse[j]); + } + } + + return embeddings; + } + + /** + * Method to generate an embedding for a single document. Calls the + * embeddingWithRetry method with the document as the input. + * @param text Document to generate an embedding for. + * @returns Promise that resolves to an embedding for the document. + */ + async embedQuery(text: string): Promise { + const params = this.getParams([ + this.stripNewLines ? text.replace(/\n/g, " ") : text, + ]); + + const embeddings = (await this.embeddingWithRetry(params)) || [[]]; + return embeddings[0]; + } + + /** + * Method to generate an embedding params. + * @param texts Array of documents to generate embeddings for. + * @returns an embedding params. + */ + private getParams( + texts: EmbeddingCreateParams["input"] + ): EmbeddingCreateParams { + return { + input: texts, + }; + } + + /** + * Private method to make a request to the BaiduAI API to generate + * embeddings. Handles the retry logic and returns the response from the + * API. + * @param request Request to send to the BaiduAI API. + * @returns Promise that resolves to the response from the API. + */ + private async embeddingWithRetry(body: EmbeddingCreateParams) { + if (!this.accessToken) { + this.accessToken = await this.getAccessToken(); + } + + return fetch( + `https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/embeddings/${this.modelName}?access_token=${this.accessToken}`, + { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(body), + } + ).then(async (response) => { + const embeddingData: EmbeddingResponse | EmbeddingErrorResponse = + await response.json(); + + if ("error_code" in embeddingData && embeddingData.error_code) { + throw new Error( + `${embeddingData.error_code}: ${embeddingData.error_msg}` + ); + } + + return (embeddingData as EmbeddingResponse).data.map( + ({ embedding }) => embedding + ); + }); + } + + /** + * Method that retrieves the access token for making requests to the Baidu + * API. + * @returns The access token for making requests to the Baidu API. + */ + private async getAccessToken() { + const url = `https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=${this.baiduApiKey}&client_secret=${this.baiduSecretKey}`; + const response = await fetch(url, { + method: "POST", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + }); + if (!response.ok) { + const text = await response.text(); + const error = new Error( + `Baidu get access token failed with status code ${response.status}, response: ${text}` + ); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (error as any).response = response; + throw error; + } + const json = await response.json(); + return json.access_token; + } +} diff --git a/libs/langchain-community/src/embeddings/tests/baidu_qianfan.int.test.ts b/libs/langchain-community/src/embeddings/tests/baidu_qianfan.int.test.ts new file mode 100644 index 000000000000..fd4db0252e0e --- /dev/null +++ b/libs/langchain-community/src/embeddings/tests/baidu_qianfan.int.test.ts @@ -0,0 +1,34 @@ +import { test, expect } from "@jest/globals"; +import { BaiduQianfanEmbeddings } from "../baidu_qianfan.js"; + +test.skip("Test BaiduQianfanEmbeddings.embedQuery", async () => { + const embeddings = new BaiduQianfanEmbeddings(); + const res = await embeddings.embedQuery("Hello world"); + expect(typeof res[0]).toBe("number"); +}); + +test.skip("Test BaiduQianfanEmbeddings.embedDocuments", async () => { + const embeddings = new BaiduQianfanEmbeddings(); + const res = await embeddings.embedDocuments(["Hello world", "Bye bye"]); + expect(res).toHaveLength(2); + expect(typeof res[0][0]).toBe("number"); + expect(typeof res[1][0]).toBe("number"); +}); + +test.skip("Test BaiduQianfanEmbeddings concurrency", async () => { + const embeddings = new BaiduQianfanEmbeddings({ + batchSize: 1, + }); + const res = await embeddings.embedDocuments([ + "Hello world", + "Bye bye", + "Hello world", + "Bye bye", + "Hello world", + "Bye bye", + ]); + expect(res).toHaveLength(6); + expect(res.find((embedding) => typeof embedding[0] !== "number")).toBe( + undefined + ); +}); From 4b3e8d20e48a1c6bc3a07c407858931ff3cc440b Mon Sep 17 00:00:00 2001 From: Mohammed Bilal Shareef Date: Tue, 9 Apr 2024 06:18:16 +0530 Subject: [PATCH 03/15] Fix issue in Neo4jGraph.addGraphDocuments function where Document node is not populating text content (#5008) --- libs/langchain-community/src/graphs/neo4j_graph.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/langchain-community/src/graphs/neo4j_graph.ts b/libs/langchain-community/src/graphs/neo4j_graph.ts index d51876616a10..ab62d4d91c3f 100644 --- a/libs/langchain-community/src/graphs/neo4j_graph.ts +++ b/libs/langchain-community/src/graphs/neo4j_graph.ts @@ -43,7 +43,7 @@ export const BASE_ENTITY_LABEL = "__Entity__"; const INCLUDE_DOCS_QUERY = ` MERGE (d:Document {id:$document.metadata.id}) - SET d.text = $document.page_content + SET d.text = $document.pageContent SET d += $document.metadata WITH d `; From 888d3fcbe38f71ee40cb4bc66920fb305a6fb80a Mon Sep 17 00:00:00 2001 From: Julian Gomez <56138728+DevJaGz@users.noreply.github.com> Date: Mon, 8 Apr 2024 19:50:18 -0500 Subject: [PATCH 04/15] docs[patch]: Fix typo in retrievers section (#5002) * docs: fix typo in "retrievers" section * Format --------- Co-authored-by: jgomezimexhs Co-authored-by: jacoblee93 --- .../core_docs/docs/modules/data_connection/retrievers/index.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/core_docs/docs/modules/data_connection/retrievers/index.mdx b/docs/core_docs/docs/modules/data_connection/retrievers/index.mdx index e55da71a3303..a9734392f90b 100644 --- a/docs/core_docs/docs/modules/data_connection/retrievers/index.mdx +++ b/docs/core_docs/docs/modules/data_connection/retrievers/index.mdx @@ -29,7 +29,7 @@ LangChain provides several advanced retrieval types. A full list is below, along | [Vectorstore](/docs/modules/data_connection/retrievers/vectorstore) | Vectorstore | No | If you are just getting started and looking for something quick and easy. | This is the simplest method and the one that is easiest to get started with. It involves creating embeddings for each piece of text. | | [ParentDocument](/docs/modules/data_connection/retrievers/parent-document-retriever) | Vectorstore + Document Store | No | If your pages have lots of smaller pieces of distinct information that are best indexed by themselves, but best retrieved all together. | This involves indexing multiple chunks for each document. Then you find the chunks that are most similar in embedding space, but you retrieve the whole parent document and return that (rather than individual chunks). | | [Multi Vector](/docs/modules/data_connection/retrievers/multi-vector-retriever) | Vectorstore + Document Store | Sometimes during indexing | If you are able to extract information from documents that you think is more relevant to index than the text itself. | This involves creating multiple vectors for each document. Each vector could be created in a myriad of ways - examples include summaries of the text and hypothetical questions. | -| [Self Query](/docs/modules/data_connection/retrievers/self_query/) | Vectorstore | Yes | If users are asking questions that are better answered by fetching documents based on metadata rather than similarity with the text. | This uses an LLM to transform user input into two things: (1) a string to look up semantically, (2) a metadata filer to go along with it. This is useful because oftentimes questions are about the METADATA of documents (not the content itself). | +| [Self Query](/docs/modules/data_connection/retrievers/self_query/) | Vectorstore | Yes | If users are asking questions that are better answered by fetching documents based on metadata rather than similarity with the text. | This uses an LLM to transform user input into two things: (1) a string to look up semantically, (2) a metadata filter to go along with it. This is useful because oftentimes questions are about the METADATA of documents (not the content itself). | | [Contextual Compression](/docs/modules/data_connection/retrievers/contextual_compression) | Any | Sometimes | If you are finding that your retrieved documents contain too much irrelevant information and are distracting the LLM. | This puts a post-processing step on top of another retriever and extracts only the most relevant information from retrieved documents. This can be done with embeddings or an LLM. | | [Time-Weighted Vectorstore](/docs/modules/data_connection/retrievers/time_weighted_vectorstore) | Vectorstore | No | If you have timestamps associated with your documents, and you want to retrieve the most recent ones | This fetches documents based on a combination of semantic similarity (as in normal vector retrieval) and recency (looking at timestamps of indexed documents) | | [Multi-Query Retriever](/docs/modules/data_connection/retrievers/multi-query-retriever) | Any | Yes | If users are asking questions that are complex and require multiple pieces of distinct information to respond | This uses an LLM to generate multiple queries from the original one. This is useful when the original query needs pieces of information about multiple topics to be properly answered. By generating multiple queries, we can then fetch documents for each of them. | From be4f8b751bfe05a727dab72b713038fa6c5f67b0 Mon Sep 17 00:00:00 2001 From: Tomaz Bratanic Date: Tue, 9 Apr 2024 02:50:37 +0200 Subject: [PATCH 05/15] docs[patch]: Add main graph construction docs (#4985) * Add main graph construction docs * fix linnks --- .../docs/use_cases/graph/construction.ipynb | 253 ++++++++++++++++++ .../docs/use_cases/graph/index.ipynb | 24 +- .../docs/use_cases/graph/quickstart.ipynb | 12 +- .../static/img/graph_construction1.png | Bin 0 -> 68572 bytes .../static/img/graph_construction2.png | Bin 0 -> 60577 bytes 5 files changed, 277 insertions(+), 12 deletions(-) create mode 100644 docs/core_docs/docs/use_cases/graph/construction.ipynb create mode 100644 docs/core_docs/static/img/graph_construction1.png create mode 100644 docs/core_docs/static/img/graph_construction2.png diff --git a/docs/core_docs/docs/use_cases/graph/construction.ipynb b/docs/core_docs/docs/use_cases/graph/construction.ipynb new file mode 100644 index 000000000000..c7c5808ac99f --- /dev/null +++ b/docs/core_docs/docs/use_cases/graph/construction.ipynb @@ -0,0 +1,253 @@ +{ + "cells": [ + { + "cell_type": "raw", + "id": "5e61b0f2-15b9-4241-9ab5-ff0f3f732232", + "metadata": {}, + "source": [ + "---\n", + "sidebar_position: 1\n", + "---" + ] + }, + { + "cell_type": "markdown", + "id": "846ef4f4-ee38-4a42-a7d3-1a23826e4830", + "metadata": {}, + "source": [ + "# Constructing knowledge graphs\n", + "In this guide we'll go over the basic ways of constructing a knowledge graph based on unstructured text. The constructured graph can then be used as knowledge base in a RAG application. At a high-level, the steps of constructing a knowledge are from text are:\n", + "\n", + "1. Extracting structured information from text: Model is used to extract structured graph information from text.\n", + "2. Storing into graph database: Storing the extracted structured graph information into a graph database enables downstream RAG applications" + ] + }, + { + "cell_type": "markdown", + "id": "26677b08", + "metadata": {}, + "source": [ + "## Setup\n", + "#### Install dependencies\n", + "\n", + "```{=mdx}\n", + "import IntegrationInstallTooltip from \"@mdx_components/integration_install_tooltip.mdx\";\n", + "import Npm2Yarn from \"@theme/Npm2Yarn\";\n", + "\n", + "\n", + "\n", + "\n", + " langchain @langchain/community @langchain/openai neo4j-driver zod\n", + "\n", + "```\n", + "\n", + "#### Set environment variables\n", + "\n", + "We'll use OpenAI in this example:\n", + "\n", + "```env\n", + "OPENAI_API_KEY=your-api-key\n", + "\n", + "# Optional, use LangSmith for best-in-class observability\n", + "LANGSMITH_API_KEY=your-api-key\n", + "LANGCHAIN_TRACING_V2=true\n", + "```\n", + "\n", + "Next, we need to define Neo4j credentials.\n", + "Follow [these installation steps](https://neo4j.com/docs/operations-manual/current/installation/) to set up a Neo4j database.\n", + "\n", + "```env\n", + "NEO4J_URI=\"bolt://localhost:7687\"\n", + "NEO4J_USERNAME=\"neo4j\"\n", + "NEO4J_PASSWORD=\"password\"\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "50fa4510-29b7-49b6-8496-5e86f694e81f", + "metadata": {}, + "source": [ + "The below example will create a connection with a Neo4j database." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4ee9ef7a-eef9-4289-b9fd-8fbc31041688", + "metadata": {}, + "outputs": [], + "source": [ + "import \"neo4j-driver\";\n", + "import { Neo4jGraph } from \"@langchain/community/graphs/neo4j_graph\";\n", + "\n", + "const url = Deno.env.get(\"NEO4J_URI\");\n", + "const username = Deno.env.get(\"NEO4J_USER\");\n", + "const password = Deno.env.get(\"NEO4J_PASSWORD\");\n", + "const graph = await Neo4jGraph.initialize({ url, username, password });" + ] + }, + { + "cell_type": "markdown", + "id": "0cb0ea30-ca55-4f35-aad6-beb57453de66", + "metadata": {}, + "source": [ + "## LLM Graph Transformer\n", + "Extracting graph data from text enables the transformation of unstructured information into structured formats, facilitating deeper insights and more efficient navigation through complex relationships and patterns. The LLMGraphTransformer converts text documents into structured graph documents by leveraging a LLM to parse and categorize entities and their relationships. The selection of the LLM model significantly influences the output by determining the accuracy and nuance of the extracted graph data." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "e1a19424-6046-40c2-81d1-f3b88193a293", + "metadata": {}, + "outputs": [], + "source": [ + "import { ChatOpenAI } from \"@langchain/openai\";\n", + "import { LLMGraphTransformer } from \"@langchain/community/experimental/graph_transformers/llm\";\n", + "\n", + "const model = new ChatOpenAI({\n", + " temperature: 0,\n", + " modelName: \"gpt-4-turbo-preview\",\n", + "});\n", + "\n", + "const llmGraphTransformer = new LLMGraphTransformer({\n", + " llm: model\n", + "});\n" + ] + }, + { + "cell_type": "markdown", + "id": "9c14084c-37a7-4a9c-a026-74e12961c781", + "metadata": {}, + "source": [ + "Now we can pass in example text and examine the results." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "bbfe0d8f-982e-46e6-88fb-8a4f0d850b07", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Nodes: 8\n", + "Relationships:7\n" + ] + } + ], + "source": [ + "import { Document } from \"@langchain/core/documents\";\n", + "\n", + "let text = `\n", + "Marie Curie, was a Polish and naturalised-French physicist and chemist who conducted pioneering research on radioactivity.\n", + "She was the first woman to win a Nobel Prize, the first person to win a Nobel Prize twice, and the only person to win a Nobel Prize in two scientific fields.\n", + "Her husband, Pierre Curie, was a co-winner of her first Nobel Prize, making them the first-ever married couple to win the Nobel Prize and launching the Curie family legacy of five Nobel Prizes.\n", + "She was, in 1906, the first woman to become a professor at the University of Paris.\n", + "`\n", + "\n", + "const result = await llmGraphTransformer.convertToGraphDocuments([\n", + " new Document({ pageContent: text }),\n", + "]);\n", + "\n", + "console.log(`Nodes: ${result[0].nodes.length}`);\n", + "console.log(`Relationships:${result[0].relationships.length}`);" + ] + }, + { + "cell_type": "markdown", + "id": "a8afbf13-05d0-4383-8050-f88b8c2f6fab", + "metadata": {}, + "source": [ + "Note that the graph construction process is non-deterministic since we are using LLM. Therefore, you might get slightly different results on each execution.\n", + "Examine the following image to better grasp the structure of the generated knowledge graph.\n", + "\n", + "![graph_construction1.png](../../../static/img/graph_construction1.png)\n", + "\n", + "Additionally, you have the flexibility to define specific types of nodes and relationships for extraction according to your requirements." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "6f92929f-74fb-4db2-b7e1-eb1e9d386a67", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Nodes: 6\n", + "Relationships:4\n" + ] + } + ], + "source": [ + "const llmGraphTransformerFiltered = new LLMGraphTransformer({\n", + " llm: model,\n", + " allowedNodes: [\"PERSON\", \"COUNTRY\", \"ORGANIZATION\"],\n", + " allowedRelationships:[\"NATIONALITY\", \"LOCATED_IN\", \"WORKED_AT\", \"SPOUSE\"],\n", + " strictMode:false\n", + "});\n", + "\n", + "const result_filtered = await llmGraphTransformerFiltered.convertToGraphDocuments([\n", + " new Document({ pageContent: text }),\n", + "]);\n", + "\n", + "console.log(`Nodes: ${result_filtered[0].nodes.length}`);\n", + "console.log(`Relationships:${result_filtered[0].relationships.length}`);" + ] + }, + { + "cell_type": "markdown", + "id": "f66c6756-6efb-4b1e-9b5d-87ed914a5212", + "metadata": {}, + "source": [ + "For a better understanding of the generated graph, we can again visualize it.\n", + "\n", + "![graph_construction1.png](../../../static/img/graph_construction2.png)\n", + "\n", + "## Storing to graph database\n", + "The generated graph documents can be stored to a graph database using the `addGraphDocuments` method." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "8ef3e21d-f1c2-45e2-9511-4920d1cf6e7e", + "metadata": {}, + "outputs": [], + "source": [ + "await graph.addGraphDocuments(result_filtered)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e67382aa-7324-4983-b834-1fdd841cc92c", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Deno", + "language": "typescript", + "name": "deno" + }, + "language_info": { + "file_extension": ".ts", + "mimetype": "text/x.typescript", + "name": "typescript", + "nb_converter": "script", + "pygments_lexer": "typescript", + "version": "5.4.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/core_docs/docs/use_cases/graph/index.ipynb b/docs/core_docs/docs/use_cases/graph/index.ipynb index 43d28138957f..1c5b57af94e8 100644 --- a/docs/core_docs/docs/use_cases/graph/index.ipynb +++ b/docs/core_docs/docs/use_cases/graph/index.ipynb @@ -32,8 +32,16 @@ "\n", "* [Prompting strategies](/docs/use_cases/graph/prompting): Advanced prompt engineering techniques.\n", "* [Mapping values](/docs/use_cases/graph/mapping): Techniques for mapping values from questions to database.\n", - "* [Semantic layer](/docs/use_cases/graph/semantic): Techniques for working implementing semantic layers." + "* [Semantic layer](/docs/use_cases/graph/semantic): Techniques for working implementing semantic layers.\n", + "* [Constructing graphs](/docs/use_cases/graph/construction): Techniques for constructing knowledge graphs.\n" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { @@ -43,16 +51,12 @@ "name": "deno" }, "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", + "file_extension": ".ts", + "mimetype": "text/x.typescript", "name": "typescript", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.5" + "nb_converter": "script", + "pygments_lexer": "typescript", + "version": "5.4.3" } }, "nbformat": 4, diff --git a/docs/core_docs/docs/use_cases/graph/quickstart.ipynb b/docs/core_docs/docs/use_cases/graph/quickstart.ipynb index b0582fdc79bb..bea82cf95dcc 100644 --- a/docs/core_docs/docs/use_cases/graph/quickstart.ipynb +++ b/docs/core_docs/docs/use_cases/graph/quickstart.ipynb @@ -225,8 +225,16 @@ "\n", "* [Prompting strategies](/docs/use_cases/graph/prompting): Advanced prompt engineering techniques.\n", "* [Mapping values](/docs/use_cases/graph/mapping): Techniques for mapping values from questions to database.\n", - "* [Semantic layer](/docs/use_cases/graph/semantic): Techniques for working implementing semantic layers." + "* [Semantic layer](/docs/use_cases/graph/semantic): Techniques for working implementing semantic layers.\n", + "* [Constructing graphs](/docs/use_cases/graph/construction): Techniques for constructing knowledge graphs.\n" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { @@ -241,7 +249,7 @@ "name": "typescript", "nb_converter": "script", "pygments_lexer": "typescript", - "version": "5.3.3" + "version": "5.4.3" } }, "nbformat": 4, diff --git a/docs/core_docs/static/img/graph_construction1.png b/docs/core_docs/static/img/graph_construction1.png new file mode 100644 index 0000000000000000000000000000000000000000..9639f751e6ca003a31631c47307a7e2dda0e32f2 GIT binary patch literal 68572 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 literal 0 HcmV?d00001 diff --git a/docs/core_docs/static/img/graph_construction2.png b/docs/core_docs/static/img/graph_construction2.png new file mode 100644 index 0000000000000000000000000000000000000000..4e34adc95bb6933405cf2e5fedbddfcb63c1b114 GIT binary patch literal 60577 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 L$})vdj9>i+I8IQT literal 0 HcmV?d00001 From a2e436e800de8d23894aff31adc14cec8dfca2a0 Mon Sep 17 00:00:00 2001 From: Tomaz Bratanic Date: Tue, 9 Apr 2024 02:58:32 +0200 Subject: [PATCH 06/15] community[patch]: Fix strict mode comparison and formatting for llm graph transformer (#4988) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix strict mode comparison and formatting for llm graph transformer * Map only once, extend serializable. * formatting * lc namespace * formattting --------- Co-authored-by: Anej Gorkič --- .../graph_transformers/llm.int.test.ts | 47 +++++++++++++++++-- .../experimental/graph_transformers/llm.ts | 34 +++++++++++--- .../src/graphs/graph_document.ts | 10 ++-- 3 files changed, 77 insertions(+), 14 deletions(-) diff --git a/libs/langchain-community/src/experimental/graph_transformers/llm.int.test.ts b/libs/langchain-community/src/experimental/graph_transformers/llm.int.test.ts index 39948f7fef14..8702c1cff782 100644 --- a/libs/langchain-community/src/experimental/graph_transformers/llm.int.test.ts +++ b/libs/langchain-community/src/experimental/graph_transformers/llm.int.test.ts @@ -45,13 +45,52 @@ test("convertToGraphDocuments with allowed", async () => { expect(result).toEqual([ new GraphDocument({ nodes: [ - new Node({ id: "Elon Musk", type: "PERSON" }), - new Node({ id: "OpenAI", type: "ORGANIZATION" }), + new Node({ id: "Elon Musk", type: "Person" }), + new Node({ id: "OpenAI", type: "Organization" }), ], relationships: [ new Relationship({ - source: new Node({ id: "Elon Musk", type: "PERSON" }), - target: new Node({ id: "OpenAI", type: "ORGANIZATION" }), + source: new Node({ id: "Elon Musk", type: "Person" }), + target: new Node({ id: "OpenAI", type: "Organization" }), + type: "SUES", + }), + ], + source: new Document({ + pageContent: "Elon Musk is suing OpenAI", + metadata: {}, + }), + }), + ]); +}); + +test("convertToGraphDocuments with allowed lowercased", async () => { + const model = new ChatOpenAI({ + temperature: 0, + modelName: "gpt-4-turbo-preview", + }); + + const llmGraphTransformer = new LLMGraphTransformer({ + llm: model, + allowedNodes: ["Person", "Organization"], + allowedRelationships: ["SUES"], + }); + + const result = await llmGraphTransformer.convertToGraphDocuments([ + new Document({ pageContent: "Elon Musk is suing OpenAI" }), + ]); + + console.log(JSON.stringify(result)); + + expect(result).toEqual([ + new GraphDocument({ + nodes: [ + new Node({ id: "Elon Musk", type: "Person" }), + new Node({ id: "OpenAI", type: "Organization" }), + ], + relationships: [ + new Relationship({ + source: new Node({ id: "Elon Musk", type: "Person" }), + target: new Node({ id: "OpenAI", type: "Organization" }), type: "SUES", }), ], diff --git a/libs/langchain-community/src/experimental/graph_transformers/llm.ts b/libs/langchain-community/src/experimental/graph_transformers/llm.ts index b808e93abd6a..858e2b88b8f9 100644 --- a/libs/langchain-community/src/experimental/graph_transformers/llm.ts +++ b/libs/langchain-community/src/experimental/graph_transformers/llm.ts @@ -47,6 +47,13 @@ interface OptionalEnumFieldProps { fieldKwargs?: object; } +function toTitleCase(str: string): string { + return str + .split(" ") + .map((w) => w[0].toUpperCase() + w.substring(1).toLowerCase()) + .join(""); +} + function createOptionalEnumType({ enumValues = undefined, description = "", @@ -122,7 +129,7 @@ function createSchema(allowedNodes: string[], allowedRelationships: string[]) { function mapToBaseNode(node: any): Node { return new Node({ id: node.id, - type: node.type.replace(" ", "_").toUpperCase(), + type: toTitleCase(node.type), }); } @@ -131,11 +138,11 @@ function mapToBaseRelationship(relationship: any): Relationship { return new Relationship({ source: new Node({ id: relationship.sourceNodeId, - type: relationship.sourceNodeType.replace(" ", "_").toUpperCase(), + type: toTitleCase(relationship.sourceNodeType), }), target: new Node({ id: relationship.targetNodeId, - type: relationship.targetNodeType.replace(" ", "_").toUpperCase(), + type: toTitleCase(relationship.targetNodeType), }), type: relationship.relationshipType.replace(" ", "_").toUpperCase(), }); @@ -208,16 +215,29 @@ export class LLMGraphTransformer { (this.allowedNodes.length > 0 || this.allowedRelationships.length > 0) ) { if (this.allowedNodes.length > 0) { - nodes = nodes.filter((node) => this.allowedNodes.includes(node.type)); + const allowedNodesLowerCase = this.allowedNodes.map((node) => + node.toLowerCase() + ); + + // For nodes, compare lowercased types + nodes = nodes.filter((node) => + allowedNodesLowerCase.includes(node.type.toLowerCase()) + ); + + // For relationships, compare lowercased types for both source and target nodes relationships = relationships.filter( (rel) => - this.allowedNodes.includes(rel.source.type) && - this.allowedNodes.includes(rel.target.type) + allowedNodesLowerCase.includes(rel.source.type.toLowerCase()) && + allowedNodesLowerCase.includes(rel.target.type.toLowerCase()) ); } + if (this.allowedRelationships.length > 0) { + // For relationships, compare lowercased types relationships = relationships.filter((rel) => - this.allowedRelationships.includes(rel.type) + this.allowedRelationships + .map((rel) => rel.toLowerCase()) + .includes(rel.type.toLowerCase()) ); } } diff --git a/libs/langchain-community/src/graphs/graph_document.ts b/libs/langchain-community/src/graphs/graph_document.ts index 939817a5623d..36a17c053e4d 100644 --- a/libs/langchain-community/src/graphs/graph_document.ts +++ b/libs/langchain-community/src/graphs/graph_document.ts @@ -60,14 +60,14 @@ export class Relationship extends Serializable { } } -export class GraphDocument extends Document { +export class GraphDocument extends Serializable { nodes: Node[]; relationships: Relationship[]; source: Document; - lc_namespace = ["langchain", "graph", "document_node"]; + lc_namespace = ["langchain", "graph", "graph_document"]; constructor({ nodes, @@ -78,7 +78,11 @@ export class GraphDocument extends Document { relationships: Relationship[]; source: Document; }) { - super(source); + super({ + nodes, + relationships, + source, + }); this.nodes = nodes; this.relationships = relationships; this.source = source; From fb073759e37c2a746b5d1fb93d5aafb8ad34ba54 Mon Sep 17 00:00:00 2001 From: Jacob Lee Date: Mon, 8 Apr 2024 18:12:33 -0700 Subject: [PATCH 07/15] core[patch]: Release 0.1.55 (#5021) --- langchain-core/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/langchain-core/package.json b/langchain-core/package.json index 0d636564f4e7..c88208410108 100644 --- a/langchain-core/package.json +++ b/langchain-core/package.json @@ -1,6 +1,6 @@ { "name": "@langchain/core", - "version": "0.1.54", + "version": "0.1.55", "description": "Core LangChain.js abstractions and schemas", "type": "module", "engines": { From cb4309b9b12543d6e80b3b188d3e09024ff08fc8 Mon Sep 17 00:00:00 2001 From: Jacob Lee Date: Mon, 8 Apr 2024 18:18:11 -0700 Subject: [PATCH 08/15] community[patch]: Release 0.0.45 (#5022) --- libs/langchain-community/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/langchain-community/package.json b/libs/langchain-community/package.json index 303ca810d0a2..63ddd649ca06 100644 --- a/libs/langchain-community/package.json +++ b/libs/langchain-community/package.json @@ -1,6 +1,6 @@ { "name": "@langchain/community", - "version": "0.0.44", + "version": "0.0.45", "description": "Third-party integrations for LangChain.js", "type": "module", "engines": { From ab2ecef9f212ff9601620e36bbc37778a14a7ec8 Mon Sep 17 00:00:00 2001 From: jacoblee93 Date: Mon, 8 Apr 2024 18:22:30 -0700 Subject: [PATCH 09/15] Release 0.1.32 --- langchain/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/langchain/package.json b/langchain/package.json index 24d8306de772..b041adc02087 100644 --- a/langchain/package.json +++ b/langchain/package.json @@ -1,6 +1,6 @@ { "name": "langchain", - "version": "0.1.31", + "version": "0.1.32", "description": "Typescript bindings for langchain", "type": "module", "engines": { From 7efcea516e0acf3367bc81bc8b7c406a62b4090b Mon Sep 17 00:00:00 2001 From: Jacob Lee Date: Tue, 9 Apr 2024 01:17:53 -0700 Subject: [PATCH 10/15] anthropic[patch]: Add Zod validation, update Anthropic SDK version (#5026) * Add Zod validation, update Anthropic SDK version * Remove log * Lock * Fix test --- libs/langchain-anthropic/package.json | 2 +- libs/langchain-anthropic/src/chat_models.ts | 13 ++- .../tests/tool_calling.int.test.ts | 20 ++-- .../langchain-anthropic/src/output_parsers.ts | 44 +++++-- .../src/tests/chat_models.test.ts | 107 ++++++++++++++++++ yarn.lock | 11 +- 6 files changed, 170 insertions(+), 27 deletions(-) create mode 100644 libs/langchain-anthropic/src/tests/chat_models.test.ts diff --git a/libs/langchain-anthropic/package.json b/libs/langchain-anthropic/package.json index 23d7a18a82d2..46e30f16aec6 100644 --- a/libs/langchain-anthropic/package.json +++ b/libs/langchain-anthropic/package.json @@ -39,7 +39,7 @@ "author": "LangChain", "license": "MIT", "dependencies": { - "@anthropic-ai/sdk": "^0.17.2", + "@anthropic-ai/sdk": "^0.20.1", "@langchain/core": "~0.1.54", "fast-xml-parser": "^4.3.5", "zod": "^3.22.4", diff --git a/libs/langchain-anthropic/src/chat_models.ts b/libs/langchain-anthropic/src/chat_models.ts index d20a4ff7331e..c2a86d8b552b 100644 --- a/libs/langchain-anthropic/src/chat_models.ts +++ b/libs/langchain-anthropic/src/chat_models.ts @@ -527,7 +527,7 @@ export class ChatAnthropicMessages< role, content: message.content, }; - } else if ("type" in message.content) { + } else { const contentBlocks = message.content.map((contentPart) => { if (contentPart.type === "image_url") { let source; @@ -546,6 +546,15 @@ export class ChatAnthropicMessages< type: "text" as const, // Explicitly setting the type as "text" text: contentPart.text, }; + } else if (contentPart.type === "tool_use") { + // TODO: Fix when SDK types are fixed + return { + type: "tool_use" as const, + id: contentPart.id, + name: contentPart.name, + input: contentPart.input, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } as any; } else { throw new Error("Unsupported message content format"); } @@ -554,8 +563,6 @@ export class ChatAnthropicMessages< role, content: contentBlocks, }; - } else { - throw new Error("Unsupported message content format"); } }); return { diff --git a/libs/langchain-anthropic/src/experimental/tests/tool_calling.int.test.ts b/libs/langchain-anthropic/src/experimental/tests/tool_calling.int.test.ts index d8acd086ae9a..f5c863c60a88 100644 --- a/libs/langchain-anthropic/src/experimental/tests/tool_calling.int.test.ts +++ b/libs/langchain-anthropic/src/experimental/tests/tool_calling.int.test.ts @@ -7,7 +7,7 @@ import { BaseMessageChunk, HumanMessage } from "@langchain/core/messages"; import { ChatPromptTemplate } from "@langchain/core/prompts"; import { ChatAnthropicTools } from "../tool_calling.js"; -test("Test ChatAnthropicTools", async () => { +test.skip("Test ChatAnthropicTools", async () => { const chat = new ChatAnthropicTools({ modelName: "claude-3-sonnet-20240229", maxRetries: 0, @@ -17,7 +17,7 @@ test("Test ChatAnthropicTools", async () => { console.log(JSON.stringify(res)); }); -test("Test ChatAnthropicTools streaming", async () => { +test.skip("Test ChatAnthropicTools streaming", async () => { const chat = new ChatAnthropicTools({ modelName: "claude-3-sonnet-20240229", maxRetries: 0, @@ -32,7 +32,7 @@ test("Test ChatAnthropicTools streaming", async () => { expect(chunks.length).toBeGreaterThan(1); }); -test("Test ChatAnthropicTools with tools", async () => { +test.skip("Test ChatAnthropicTools with tools", async () => { const chat = new ChatAnthropicTools({ modelName: "claude-3-sonnet-20240229", temperature: 0.1, @@ -71,7 +71,7 @@ test("Test ChatAnthropicTools with tools", async () => { ); }); -test("Test ChatAnthropicTools with a forced function call", async () => { +test.skip("Test ChatAnthropicTools with a forced function call", async () => { const chat = new ChatAnthropicTools({ modelName: "claude-3-sonnet-20240229", temperature: 0.1, @@ -117,7 +117,7 @@ test("Test ChatAnthropicTools with a forced function call", async () => { ); }); -test("ChatAnthropicTools with Zod schema", async () => { +test.skip("ChatAnthropicTools with Zod schema", async () => { const schema = z.object({ people: z.array( z.object({ @@ -168,7 +168,7 @@ test("ChatAnthropicTools with Zod schema", async () => { }); }); -test("ChatAnthropicTools with parallel tool calling", async () => { +test.skip("ChatAnthropicTools with parallel tool calling", async () => { const schema = z.object({ name: z.string().describe("The name of a person"), height: z.number().describe("The person's height"), @@ -215,7 +215,7 @@ test("ChatAnthropicTools with parallel tool calling", async () => { ); }); -test("Test ChatAnthropic withStructuredOutput", async () => { +test.skip("Test ChatAnthropic withStructuredOutput", async () => { const runnable = new ChatAnthropicTools({ modelName: "claude-3-sonnet-20240229", maxRetries: 0, @@ -235,7 +235,7 @@ test("Test ChatAnthropic withStructuredOutput", async () => { expect(res).toEqual({ name: "Alex", height: 5, hairColor: "blonde" }); }); -test("Test ChatAnthropic withStructuredOutput on a single array item", async () => { +test.skip("Test ChatAnthropic withStructuredOutput on a single array item", async () => { const runnable = new ChatAnthropicTools({ modelName: "claude-3-sonnet-20240229", maxRetries: 0, @@ -258,7 +258,7 @@ test("Test ChatAnthropic withStructuredOutput on a single array item", async () }); }); -test("Test ChatAnthropic withStructuredOutput on a single array item", async () => { +test.skip("Test ChatAnthropic withStructuredOutput on a single array item", async () => { const runnable = new ChatAnthropicTools({ modelName: "claude-3-sonnet-20240229", maxRetries: 0, @@ -305,7 +305,7 @@ test("Test ChatAnthropic withStructuredOutput on a single array item", async () }); }); -test("Test ChatAnthropicTools", async () => { +test.skip("Test ChatAnthropicTools", async () => { const chat = new ChatAnthropicTools({ modelName: "claude-3-sonnet-20240229", maxRetries: 0, diff --git a/libs/langchain-anthropic/src/output_parsers.ts b/libs/langchain-anthropic/src/output_parsers.ts index 928a128c184b..8e0e72818d6a 100644 --- a/libs/langchain-anthropic/src/output_parsers.ts +++ b/libs/langchain-anthropic/src/output_parsers.ts @@ -1,10 +1,15 @@ -import { BaseLLMOutputParser } from "@langchain/core/output_parsers"; +import { z } from "zod"; +import { + BaseLLMOutputParser, + OutputParserException, +} from "@langchain/core/output_parsers"; import { JsonOutputKeyToolsParserParams } from "@langchain/core/output_parsers/openai_tools"; import { ChatGeneration } from "@langchain/core/outputs"; import { AnthropicToolResponse } from "./types.js"; -interface AnthropicToolsOutputParserParams - extends JsonOutputKeyToolsParserParams {} +// eslint-disable-next-line @typescript-eslint/no-explicit-any +interface AnthropicToolsOutputParserParams> + extends JsonOutputKeyToolsParserParams {} export class AnthropicToolsOutputParser< // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -24,10 +29,32 @@ export class AnthropicToolsOutputParser< /** Whether to return only the first tool call. */ returnSingle = false; - constructor(params: AnthropicToolsOutputParserParams) { + zodSchema?: z.ZodType; + + constructor(params: AnthropicToolsOutputParserParams) { super(params); this.keyName = params.keyName; this.returnSingle = params.returnSingle ?? this.returnSingle; + this.zodSchema = params.zodSchema; + } + + protected async _validateResult(result: unknown): Promise { + if (this.zodSchema === undefined) { + return result as T; + } + const zodParsedResult = await this.zodSchema.safeParseAsync(result); + if (zodParsedResult.success) { + return zodParsedResult.data; + } else { + throw new OutputParserException( + `Failed to parse. Text: "${JSON.stringify( + result, + null, + 2 + )}". Error: ${JSON.stringify(zodParsedResult.error.errors)}`, + JSON.stringify(result, null, 2) + ); + } } // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -45,10 +72,13 @@ export class AnthropicToolsOutputParser< | undefined; return tool; }); - if (tools.length === 0 || !tools[0]) { - throw new Error("No tools provided to AnthropicToolsOutputParser."); + if (tools[0] === undefined) { + throw new Error( + "No parseable tool calls provided to AnthropicToolsOutputParser." + ); } const [tool] = tools; - return tool.input as T; + const validatedResult = await this._validateResult(tool.input); + return validatedResult; } } diff --git a/libs/langchain-anthropic/src/tests/chat_models.test.ts b/libs/langchain-anthropic/src/tests/chat_models.test.ts new file mode 100644 index 000000000000..537c0c8e4fef --- /dev/null +++ b/libs/langchain-anthropic/src/tests/chat_models.test.ts @@ -0,0 +1,107 @@ +import { jest, test } from "@jest/globals"; +import { AIMessage } from "@langchain/core/messages"; +import { z } from "zod"; +import { OutputParserException } from "@langchain/core/output_parsers"; +import { ChatAnthropic } from "../chat_models.js"; + +test("withStructuredOutput with output validation", async () => { + const model = new ChatAnthropic({ + modelName: "claude-3-haiku-20240307", + temperature: 0, + anthropicApiKey: "testing", + }); + jest + // eslint-disable-next-line @typescript-eslint/no-explicit-any + .spyOn(model as any, "invoke") + .mockResolvedValue( + new AIMessage({ + content: [ + { + type: "tool_use", + id: "notreal", + name: "Extractor", + input: "Incorrect string tool call input", + }, + ], + }) + ); + const schema = z.object({ + alerts: z + .array( + z.object({ + description: z.string().describe("A description of the alert."), + severity: z + .enum(["HIGH", "MEDIUM", "LOW"]) + .describe("How severe the alert is."), + }) + ) + .describe( + "Important security or infrastructure alerts present in the given text." + ), + }); + + const modelWithStructuredOutput = model.withStructuredOutput(schema, { + name: "Extractor", + }); + + await expect(async () => { + await modelWithStructuredOutput.invoke(` + Enumeration of Kernel Modules via Proc + Prompt for Credentials with OSASCRIPT + User Login + Modification of Standard Authentication Module + Suspicious Automator Workflows Execution + `); + }).rejects.toThrowError(OutputParserException); +}); + +test("withStructuredOutput with proper output", async () => { + const model = new ChatAnthropic({ + modelName: "claude-3-haiku-20240307", + temperature: 0, + anthropicApiKey: "testing", + }); + jest + // eslint-disable-next-line @typescript-eslint/no-explicit-any + .spyOn(model as any, "invoke") + .mockResolvedValue( + new AIMessage({ + content: [ + { + type: "tool_use", + id: "notreal", + name: "Extractor", + input: { alerts: [{ description: "test", severity: "LOW" }] }, + }, + ], + }) + ); + const schema = z.object({ + alerts: z + .array( + z.object({ + description: z.string().describe("A description of the alert."), + severity: z + .enum(["HIGH", "MEDIUM", "LOW"]) + .describe("How severe the alert is."), + }) + ) + .describe( + "Important security or infrastructure alerts present in the given text." + ), + }); + + const modelWithStructuredOutput = model.withStructuredOutput(schema, { + name: "Extractor", + }); + + const result = await modelWithStructuredOutput.invoke(` + Enumeration of Kernel Modules via Proc + Prompt for Credentials with OSASCRIPT + User Login + Modification of Standard Authentication Module + Suspicious Automator Workflows Execution + `); + + console.log(result); +}); diff --git a/yarn.lock b/yarn.lock index ea43b4d0ded5..b78f04678e87 100644 --- a/yarn.lock +++ b/yarn.lock @@ -211,20 +211,19 @@ __metadata: languageName: node linkType: hard -"@anthropic-ai/sdk@npm:^0.17.2": - version: 0.17.2 - resolution: "@anthropic-ai/sdk@npm:0.17.2" +"@anthropic-ai/sdk@npm:^0.20.1": + version: 0.20.1 + resolution: "@anthropic-ai/sdk@npm:0.20.1" dependencies: "@types/node": ^18.11.18 "@types/node-fetch": ^2.6.4 abort-controller: ^3.0.0 agentkeepalive: ^4.2.1 - digest-fetch: ^1.3.0 form-data-encoder: 1.7.2 formdata-node: ^4.3.2 node-fetch: ^2.6.7 web-streams-polyfill: ^3.2.1 - checksum: 33480adddbbf905aadcb310bdbca2baa9e3ca25ae554c94c52b189bd8e8afe89577775dbcf902ab6fa252d3b3c6e4fe5e4973a7caaa2d3e5a813d3727cf98499 + checksum: a880088ffeb993ea835f3ec250d53bf6ba23e97c3dfc54c915843aa8cb4778849fb7b85de0a359155c36595a5a5cc1db64139d407d2e36a2423284ebfe763cce languageName: node linkType: hard @@ -8810,7 +8809,7 @@ __metadata: version: 0.0.0-use.local resolution: "@langchain/anthropic@workspace:libs/langchain-anthropic" dependencies: - "@anthropic-ai/sdk": ^0.17.2 + "@anthropic-ai/sdk": ^0.20.1 "@jest/globals": ^29.5.0 "@langchain/community": "workspace:^" "@langchain/core": ~0.1.54 From aec025fbb7fe862f86ae4c8fa5dbe4c31d3b8acd Mon Sep 17 00:00:00 2001 From: Jacob Lee Date: Tue, 9 Apr 2024 01:21:10 -0700 Subject: [PATCH 11/15] anthropic[patch]: Release 0.1.11 (#5027) --- libs/langchain-anthropic/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/langchain-anthropic/package.json b/libs/langchain-anthropic/package.json index 46e30f16aec6..dc1adad76a0c 100644 --- a/libs/langchain-anthropic/package.json +++ b/libs/langchain-anthropic/package.json @@ -1,6 +1,6 @@ { "name": "@langchain/anthropic", - "version": "0.1.10", + "version": "0.1.11", "description": "Anthropic integrations for LangChain.js", "type": "module", "engines": { From dad5849306b46a40f76178688470a14218232de1 Mon Sep 17 00:00:00 2001 From: Brace Sproul Date: Tue, 9 Apr 2024 07:41:22 -0700 Subject: [PATCH 12/15] google-common[minor]: Fix single token response issue (#5024) --- libs/langchain-google-common/src/utils/gemini.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/libs/langchain-google-common/src/utils/gemini.ts b/libs/langchain-google-common/src/utils/gemini.ts index 8882af6166b1..b79474ab3904 100644 --- a/libs/langchain-google-common/src/utils/gemini.ts +++ b/libs/langchain-google-common/src/utils/gemini.ts @@ -501,7 +501,21 @@ export function responseToChatGenerations( response: GoogleLLMResponse ): ChatGeneration[] { const parts = responseToParts(response); - const ret = parts.map((part) => partToChatGeneration(part)); + let ret = parts.map((part) => partToChatGeneration(part)); + if (ret.every((item) => typeof item.message.content === "string")) { + const combinedContent = ret.map((item) => item.message.content).join(""); + const combinedText = ret.map((item) => item.text).join(""); + ret = [ + new ChatGenerationChunk({ + message: new AIMessageChunk({ + content: combinedContent, + additional_kwargs: ret[ret.length - 1].message.additional_kwargs, + }), + text: combinedText, + generationInfo: ret[ret.length - 1].generationInfo, + }), + ]; + } return ret; } From e205723564fb930b71c91aebadbcae9c5f018efc Mon Sep 17 00:00:00 2001 From: Brace Sproul Date: Tue, 9 Apr 2024 08:43:44 -0700 Subject: [PATCH 13/15] google-common[patch]: Release 0.0.4 (#5031) --- libs/langchain-google-common/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/langchain-google-common/package.json b/libs/langchain-google-common/package.json index 1645e38f6f76..185d732f0487 100644 --- a/libs/langchain-google-common/package.json +++ b/libs/langchain-google-common/package.json @@ -1,6 +1,6 @@ { "name": "@langchain/google-common", - "version": "0.0.3", + "version": "0.0.4", "description": "Core types and classes for Google services.", "type": "module", "engines": { From 789713396174cfb63190f3cb8e17758833616d8b Mon Sep 17 00:00:00 2001 From: Brace Sproul Date: Tue, 9 Apr 2024 08:47:38 -0700 Subject: [PATCH 14/15] google-gauth[patch],google-webauth[patch]: Release 0.0.3 (#5032) --- libs/langchain-google-gauth/package.json | 4 ++-- libs/langchain-google-webauth/package.json | 4 ++-- yarn.lock | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/libs/langchain-google-gauth/package.json b/libs/langchain-google-gauth/package.json index 8d0dc322b864..2b45ded0c703 100644 --- a/libs/langchain-google-gauth/package.json +++ b/libs/langchain-google-gauth/package.json @@ -1,6 +1,6 @@ { "name": "@langchain/google-gauth", - "version": "0.0.2", + "version": "0.0.3", "description": "Google auth based authentication support for Google services", "type": "module", "engines": { @@ -40,7 +40,7 @@ "license": "MIT", "dependencies": { "@langchain/core": "~0.1.1", - "@langchain/google-common": "~0.0.3", + "@langchain/google-common": "~0.0.4", "google-auth-library": "^8.9.0" }, "devDependencies": { diff --git a/libs/langchain-google-webauth/package.json b/libs/langchain-google-webauth/package.json index 6878f8ff1574..c8935ca92d11 100644 --- a/libs/langchain-google-webauth/package.json +++ b/libs/langchain-google-webauth/package.json @@ -1,6 +1,6 @@ { "name": "@langchain/google-webauth", - "version": "0.0.2", + "version": "0.0.3", "description": "Web-based authentication support for Google services", "type": "module", "engines": { @@ -40,7 +40,7 @@ "license": "MIT", "dependencies": { "@langchain/core": "~0.1.1", - "@langchain/google-common": "~0.0.3", + "@langchain/google-common": "~0.0.4", "web-auth-library": "^1.0.3" }, "devDependencies": { diff --git a/yarn.lock b/yarn.lock index b78f04678e87..758a7b07baae 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9424,7 +9424,7 @@ __metadata: languageName: unknown linkType: soft -"@langchain/google-common@workspace:*, @langchain/google-common@workspace:libs/langchain-google-common, @langchain/google-common@~0.0.3": +"@langchain/google-common@workspace:*, @langchain/google-common@workspace:libs/langchain-google-common, @langchain/google-common@~0.0.4": version: 0.0.0-use.local resolution: "@langchain/google-common@workspace:libs/langchain-google-common" dependencies: @@ -9462,7 +9462,7 @@ __metadata: dependencies: "@jest/globals": ^29.5.0 "@langchain/core": ~0.1.1 - "@langchain/google-common": ~0.0.3 + "@langchain/google-common": ~0.0.4 "@langchain/scripts": ~0.0 "@swc/core": ^1.3.90 "@swc/jest": ^0.2.29 @@ -9588,7 +9588,7 @@ __metadata: dependencies: "@jest/globals": ^29.5.0 "@langchain/core": ~0.1.1 - "@langchain/google-common": ~0.0.3 + "@langchain/google-common": ~0.0.4 "@langchain/scripts": ~0.0 "@swc/core": ^1.3.90 "@swc/jest": ^0.2.29 From 23d71788c3c1b64ee0c64625ac6a91a18195976a Mon Sep 17 00:00:00 2001 From: Brace Sproul Date: Tue, 9 Apr 2024 08:53:47 -0700 Subject: [PATCH 15/15] google-vertexai[patch],google-vertexai-web[patch]: Release 0.0.3 (#5033) --- libs/langchain-google-vertexai-web/package.json | 4 ++-- libs/langchain-google-vertexai/package.json | 4 ++-- yarn.lock | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libs/langchain-google-vertexai-web/package.json b/libs/langchain-google-vertexai-web/package.json index 91f711743850..7ff67031130f 100644 --- a/libs/langchain-google-vertexai-web/package.json +++ b/libs/langchain-google-vertexai-web/package.json @@ -1,6 +1,6 @@ { "name": "@langchain/google-vertexai-web", - "version": "0.0.2", + "version": "0.0.3", "description": "LangChain.js support for Google Vertex AI Web", "type": "module", "engines": { @@ -40,7 +40,7 @@ "license": "MIT", "dependencies": { "@langchain/core": "~0.1.1", - "@langchain/google-webauth": "~0.0.2" + "@langchain/google-webauth": "~0.0.3" }, "devDependencies": { "@jest/globals": "^29.5.0", diff --git a/libs/langchain-google-vertexai/package.json b/libs/langchain-google-vertexai/package.json index f8e354892dcf..944b63bd47fc 100644 --- a/libs/langchain-google-vertexai/package.json +++ b/libs/langchain-google-vertexai/package.json @@ -1,6 +1,6 @@ { "name": "@langchain/google-vertexai", - "version": "0.0.2", + "version": "0.0.3", "description": "LangChain.js support for Google Vertex AI", "type": "module", "engines": { @@ -40,7 +40,7 @@ "license": "MIT", "dependencies": { "@langchain/core": "~0.1.1", - "@langchain/google-gauth": "~0.0.2" + "@langchain/google-gauth": "~0.0.3" }, "devDependencies": { "@jest/globals": "^29.5.0", diff --git a/yarn.lock b/yarn.lock index 758a7b07baae..deb9ca59faef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9456,7 +9456,7 @@ __metadata: languageName: unknown linkType: soft -"@langchain/google-gauth@workspace:libs/langchain-google-gauth, @langchain/google-gauth@~0.0.2": +"@langchain/google-gauth@workspace:libs/langchain-google-gauth, @langchain/google-gauth@~0.0.3": version: 0.0.0-use.local resolution: "@langchain/google-gauth@workspace:libs/langchain-google-gauth" dependencies: @@ -9526,7 +9526,7 @@ __metadata: dependencies: "@jest/globals": ^29.5.0 "@langchain/core": ~0.1.1 - "@langchain/google-webauth": ~0.0.2 + "@langchain/google-webauth": ~0.0.3 "@langchain/scripts": ~0.0 "@swc/core": ^1.3.90 "@swc/jest": ^0.2.29 @@ -9557,7 +9557,7 @@ __metadata: dependencies: "@jest/globals": ^29.5.0 "@langchain/core": ~0.1.1 - "@langchain/google-gauth": ~0.0.2 + "@langchain/google-gauth": ~0.0.3 "@langchain/scripts": ~0.0 "@swc/core": ^1.3.90 "@swc/jest": ^0.2.29 @@ -9582,7 +9582,7 @@ __metadata: languageName: unknown linkType: soft -"@langchain/google-webauth@workspace:libs/langchain-google-webauth, @langchain/google-webauth@~0.0.2": +"@langchain/google-webauth@workspace:libs/langchain-google-webauth, @langchain/google-webauth@~0.0.3": version: 0.0.0-use.local resolution: "@langchain/google-webauth@workspace:libs/langchain-google-webauth" dependencies: