diff --git a/.github/workflows/test-exports.yml b/.github/workflows/test-exports.yml
index 15b15338107b..bc5f0d1b16da 100644
--- a/.github/workflows/test-exports.yml
+++ b/.github/workflows/test-exports.yml
@@ -34,7 +34,7 @@ jobs:
- name: Install dependencies
run: yarn install --immutable
- name: Build
- run: yarn run build:deps && yarn workspace langchain build
+ run: yarn workspace langchain build
shell: bash
env:
SKIP_API_DOCS: true
@@ -54,7 +54,7 @@ jobs:
- name: Install dependencies
run: yarn install --immutable
- name: Build
- run: yarn run build:deps && yarn workspace langchain build
+ run: yarn workspace langchain build
shell: bash
env:
SKIP_API_DOCS: true
@@ -74,7 +74,7 @@ jobs:
- name: Install dependencies
run: yarn install --immutable
- name: Build
- run: yarn run build:deps && yarn workspace langchain build
+ run: yarn workspace langchain build
shell: bash
env:
SKIP_API_DOCS: true
@@ -94,7 +94,7 @@ jobs:
- name: Install dependencies
run: yarn install --immutable
- name: Build
- run: yarn run build:deps && yarn workspace langchain build
+ run: yarn workspace langchain build
shell: bash
env:
SKIP_API_DOCS: true
@@ -114,7 +114,7 @@ jobs:
- name: Install dependencies
run: yarn install --immutable
- name: Build
- run: yarn run build:deps && yarn workspace langchain build
+ run: yarn workspace langchain build
shell: bash
env:
SKIP_API_DOCS: true
@@ -134,7 +134,7 @@ jobs:
- name: Install dependencies
run: yarn install --immutable
- name: Build
- run: yarn run build:deps && yarn workspace langchain build
+ run: yarn workspace langchain build
shell: bash
env:
SKIP_API_DOCS: true
@@ -154,7 +154,7 @@ jobs:
# - name: Install dependencies
# run: yarn install --immutable
# - name: Build
- # run: yarn run build:deps && yarn workspace langchain build
+ # run: yarn workspace langchain build
# shell: bash
# env:
# SKIP_API_DOCS: true
diff --git a/README.md b/README.md
index 21a4619ab658..c5bf7bec6d6f 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
⚡ Building applications with LLMs through composability ⚡
[![CI](https://github.com/langchain-ai/langchainjs/actions/workflows/ci.yml/badge.svg)](https://github.com/langchain-ai/langchainjs/actions/workflows/ci.yml) ![npm](https://img.shields.io/npm/dw/langchain) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Twitter](https://img.shields.io/twitter/url/https/twitter.com/langchainai.svg?style=social&label=Follow%20%40LangChainAI)](https://twitter.com/langchainai) [![](https://dcbadge.vercel.app/api/server/6adMQxSpJS?compact=true&style=flat)](https://discord.gg/6adMQxSpJS) [![Open in Dev Containers](https://img.shields.io/static/v1?label=Dev%20Containers&message=Open&color=blue&logo=visualstudiocode)](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/langchain-ai/langchainjs)
-[](https://codespaces.new/hwchase17/langchainjs)
+[](https://codespaces.new/langchain-ai/langchainjs)
Looking for the Python version? Check out [LangChain](https://github.com/langchain-ai/langchain).
diff --git a/docker-compose.yml b/docker-compose.yml
index f050399fc8a9..96953fb115ce 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -2,6 +2,9 @@ version: "3"
services:
test-exports-esbuild:
image: node:18
+ environment:
+ PUPPETEER_SKIP_DOWNLOAD: "true"
+ PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: "true"
working_dir: /app
volumes:
- ./yarn.lock:/root/yarn.lock
@@ -11,11 +14,15 @@ services:
- ./environment_tests/scripts:/scripts
- ./langchain:/langchain
- ./langchain-core:/langchain-core
+ - ./libs/langchain-community:/langchain-community
- ./libs/langchain-anthropic:/langchain-anthropic
- ./libs/langchain-openai:/langchain-openai
command: bash /scripts/docker-ci-entrypoint.sh
test-exports-esm:
image: node:18
+ environment:
+ PUPPETEER_SKIP_DOWNLOAD: "true"
+ PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: "true"
working_dir: /app
volumes:
- ./yarn.lock:/root/yarn.lock
@@ -25,11 +32,15 @@ services:
- ./environment_tests/scripts:/scripts
- ./langchain:/langchain
- ./langchain-core:/langchain-core
+ - ./libs/langchain-community:/langchain-community
- ./libs/langchain-anthropic:/langchain-anthropic
- ./libs/langchain-openai:/langchain-openai
command: bash /scripts/docker-ci-entrypoint.sh
test-exports-cjs:
image: node:18
+ environment:
+ PUPPETEER_SKIP_DOWNLOAD: "true"
+ PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: "true"
working_dir: /app
volumes:
- ./yarn.lock:/root/yarn.lock
@@ -39,11 +50,15 @@ services:
- ./environment_tests/scripts:/scripts
- ./langchain:/langchain
- ./langchain-core:/langchain-core
+ - ./libs/langchain-community:/langchain-community
- ./libs/langchain-anthropic:/langchain-anthropic
- ./libs/langchain-openai:/langchain-openai
command: bash /scripts/docker-ci-entrypoint.sh
test-exports-cf:
image: node:18
+ environment:
+ PUPPETEER_SKIP_DOWNLOAD: "true"
+ PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: "true"
working_dir: /app
volumes:
- ./yarn.lock:/root/yarn.lock
@@ -53,11 +68,15 @@ services:
- ./environment_tests/scripts:/scripts
- ./langchain:/langchain
- ./langchain-core:/langchain-core
+ - ./libs/langchain-community:/langchain-community
- ./libs/langchain-anthropic:/langchain-anthropic
- ./libs/langchain-openai:/langchain-openai
command: bash /scripts/docker-ci-entrypoint.sh
test-exports-vercel:
image: node:18
+ environment:
+ PUPPETEER_SKIP_DOWNLOAD: "true"
+ PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: "true"
working_dir: /app
volumes:
- ./yarn.lock:/root/yarn.lock
@@ -67,11 +86,15 @@ services:
- ./environment_tests/scripts:/scripts
- ./langchain:/langchain
- ./langchain-core:/langchain-core
+ - ./libs/langchain-community:/langchain-community
- ./libs/langchain-anthropic:/langchain-anthropic
- ./libs/langchain-openai:/langchain-openai
command: bash /scripts/docker-ci-entrypoint.sh
test-exports-vite:
image: node:18
+ environment:
+ PUPPETEER_SKIP_DOWNLOAD: "true"
+ PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: "true"
working_dir: /app
volumes:
- ./yarn.lock:/root/yarn.lock
@@ -81,6 +104,7 @@ services:
- ./environment_tests/scripts:/scripts
- ./langchain:/langchain
- ./langchain-core:/langchain-core
+ - ./libs/langchain-community:/langchain-community
- ./libs/langchain-anthropic:/langchain-anthropic
- ./libs/langchain-openai:/langchain-openai
command: bash /scripts/docker-ci-entrypoint.sh
@@ -92,6 +116,7 @@ services:
# - ./environment_tests/scripts:/scripts
# - ./langchain:/langchain-workspace
# - ./langchain-core:/langchain-core
+ # - ./libs/langchain-community:/langchain-community-workspace
# - ./libs/langchain-anthropic:/langchain-anthropic-workspace
# command: bash /scripts/docker-bun-ci-entrypoint.sh
success:
diff --git a/docs/api_refs/package.json b/docs/api_refs/package.json
index 3008943d4996..ba710e4f14e9 100644
--- a/docs/api_refs/package.json
+++ b/docs/api_refs/package.json
@@ -5,10 +5,13 @@
"scripts": {
"dev": "next dev -p 3001",
"typedoc": "npx typedoc --options typedoc.json",
- "build:scripts": "node ./scripts/generate-api-refs.js && node ./scripts/update-typedoc-css.js",
- "build": "yarn run build:deps && yarn workspace langchain build && yarn build:scripts && next build",
+ "build:scripts": "yarn typedoc && node ./scripts/update-typedoc-css.js",
+ "build": "yarn clean && yarn run build:deps && yarn build:scripts && next build",
+ "build:vercel": "yarn clean && yarn run build:deps --force && yarn build:scripts && next build",
+ "build:deps": "yarn run turbo:command build --filter=@langchain/core --filter=@langchain/anthropic --filter=@langchain/openai --filter=@langchain/community --filter=langchain --concurrency=1",
"start": "yarn build && next start -p 3001",
- "lint": "next lint"
+ "lint": "next lint",
+ "clean": "rm -rf .next .turbo public/ && mkdir public"
},
"dependencies": {
"next": "14.0.1",
diff --git a/docs/api_refs/scripts/generate-api-refs.js b/docs/api_refs/scripts/generate-api-refs.js
deleted file mode 100644
index 2532c01ee05b..000000000000
--- a/docs/api_refs/scripts/generate-api-refs.js
+++ /dev/null
@@ -1,104 +0,0 @@
-const { Project, SyntaxKind } = require("ts-morph");
-const { exec } = require("child_process");
-
-async function updateCodeWithIgnoreTags(tsConfigFilePath) {
- const project = new Project({
- tsConfigFilePath,
- });
- const sourceFiles = project.getSourceFiles();
- /**
- * @type {Array>}
- */
- let changes = [];
-
- const syntaxTypes = [
- SyntaxKind.MethodDeclaration,
- SyntaxKind.PropertyDeclaration,
- SyntaxKind.GetAccessor,
- SyntaxKind.SetAccessor,
- SyntaxKind.MethodSignature,
- SyntaxKind.PropertySignature,
- ];
-
- sourceFiles.forEach((sourceFile) => {
- sourceFile.getClasses().forEach((cls) => {
- // Check instance members
- cls.getInstanceMembers().forEach((member) => {
- checkMember(member);
- });
-
- // Check static members
- cls.getStaticMembers().forEach((member) => {
- checkMember(member);
- });
- });
- });
-
- function checkMember(member) {
- if (syntaxTypes.includes(member.getKind())) {
- const name = member.getName();
- if (name.startsWith("_") || name.startsWith("lc_")) {
- const jsDocs = member.getJsDocs();
- const hasIgnoreTag = jsDocs.some((jsDoc) =>
- jsDoc.getTags().some((tag) => tag.getTagName() === "ignore")
- );
- if (!hasIgnoreTag) {
- const jsDocText = `/** @ignore */\n `;
- const start = member.getStart();
- changes.push({
- sourceFile: member.getSourceFile(),
- start,
- jsDocText,
- });
- }
- }
- }
- }
-
- // Sort changes in reverse order by start position so updating
- // the source file doesn't mess up the start position of the next change
- changes.sort((a, b) => b.start - a.start);
- // Apply changes after iterating over the AST
- changes.forEach(({ sourceFile, start, jsDocText }) => {
- sourceFile.insertText(start, jsDocText);
- });
-
- await project.save();
-}
-
-async function copyLangChain(pathToLangChain) {
- try {
- await execAsync(`rm -rf ./langchain`);
- } catch (_) {
- // no-op
- }
- await execAsync(`cp -r ${pathToLangChain} ./langchain`);
- return {
- rootPath: `${process.cwd()}/langchain`,
- tsConfigPath: `${process.cwd()}/langchain/tsconfig.json`,
- };
-}
-
-async function deleteLangChain(pathToLangChain) {
- // delete the langchain dir
- await execAsync(`rm -rf ${pathToLangChain}`);
-}
-
-const execAsync = async (command, options) => new Promise((resolve, reject) => {
- exec(command, options, (err, stdout, stderr) => {
- if (err) {
- reject(err);
- } else {
- resolve(stdout);
- }
- });
-});
-
-async function main() {
- const pathToLangChain = "../../langchain";
- const { rootPath, tsConfigPath } = await copyLangChain(pathToLangChain);
- await updateCodeWithIgnoreTags(tsConfigPath);
- await execAsync("yarn typedoc");
- await deleteLangChain(rootPath);
-}
-main();
diff --git a/docs/api_refs/typedoc.json b/docs/api_refs/typedoc.json
index 378c86f4d173..8fa89bf172a8 100644
--- a/docs/api_refs/typedoc.json
+++ b/docs/api_refs/typedoc.json
@@ -8,7 +8,10 @@
"required-first",
"alphabetical"
],
- "tsconfig": "./langchain/tsconfig.json",
+ "plugin": [
+ "./typedoc_plugins/hide_underscore_lc.js"
+ ],
+ "tsconfig": "../../langchain/tsconfig.json",
"readme": "none",
"excludePrivate": true,
"excludeInternal": true,
@@ -18,285 +21,285 @@
"sourceLinkTemplate": "https://github.com/langchain-ai/langchainjs/blob/{gitRevision}/{path}#L{line}",
"logLevel": "Error",
"entryPoints": [
- "./langchain/src/load/index.ts",
- "./langchain/src/load/serializable.ts",
- "./langchain/src/agents/index.ts",
- "./langchain/src/agents/load.ts",
- "./langchain/src/agents/toolkits/index.ts",
- "./langchain/src/agents/toolkits/aws_sfn.ts",
- "./langchain/src/agents/toolkits/connery/index.ts",
- "./langchain/src/agents/toolkits/sql/index.ts",
- "./langchain/src/agents/format_scratchpad/openai_functions.ts",
- "./langchain/src/agents/format_scratchpad/openai_tools.ts",
- "./langchain/src/agents/format_scratchpad/log.ts",
- "./langchain/src/agents/format_scratchpad/xml.ts",
- "./langchain/src/agents/format_scratchpad/log_to_message.ts",
- "./langchain/src/agents/react/output_parser.ts",
- "./langchain/src/agents/xml/output_parser.ts",
- "./langchain/src/agents/openai/output_parser.ts",
- "./langchain/src/base_language/index.ts",
- "./langchain/src/tools/index.ts",
- "./langchain/src/tools/aws_lambda.ts",
- "./langchain/src/tools/aws_sfn.ts",
- "./langchain/src/tools/calculator.ts",
- "./langchain/src/tools/connery.ts",
- "./langchain/src/tools/render.ts",
- "./langchain/src/tools/sql.ts",
- "./langchain/src/tools/webbrowser.ts",
- "./langchain/src/tools/gmail/index.ts",
- "./langchain/src/tools/google_calendar/index.ts",
- "./langchain/src/tools/google_places.ts",
- "./langchain/src/chains/index.ts",
- "./langchain/src/chains/combine_documents/reduce.ts",
- "./langchain/src/chains/load.ts",
- "./langchain/src/chains/openai_functions/index.ts",
- "./langchain/src/chains/query_constructor/index.ts",
- "./langchain/src/chains/query_constructor/ir.ts",
- "./langchain/src/chains/sql_db/index.ts",
- "./langchain/src/chains/graph_qa/cypher.ts",
- "./langchain/src/embeddings/base.ts",
- "./langchain/src/embeddings/bedrock.ts",
- "./langchain/src/embeddings/cache_backed.ts",
- "./langchain/src/embeddings/cloudflare_workersai.ts",
- "./langchain/src/embeddings/fake.ts",
- "./langchain/src/embeddings/ollama.ts",
- "./langchain/src/embeddings/openai.ts",
- "./langchain/src/embeddings/cohere.ts",
- "./langchain/src/embeddings/tensorflow.ts",
- "./langchain/src/embeddings/hf.ts",
- "./langchain/src/embeddings/hf_transformers.ts",
- "./langchain/src/embeddings/googlevertexai.ts",
- "./langchain/src/embeddings/googlepalm.ts",
- "./langchain/src/embeddings/minimax.ts",
- "./langchain/src/embeddings/voyage.ts",
- "./langchain/src/embeddings/llama_cpp.ts",
- "./langchain/src/embeddings/gradient_ai.ts",
- "./langchain/src/llms/load.ts",
- "./langchain/src/llms/base.ts",
- "./langchain/src/llms/openai.ts",
- "./langchain/src/llms/ai21.ts",
- "./langchain/src/llms/aleph_alpha.ts",
- "./langchain/src/llms/cloudflare_workersai.ts",
- "./langchain/src/llms/cohere.ts",
- "./langchain/src/llms/hf.ts",
- "./langchain/src/llms/raycast.ts",
- "./langchain/src/llms/ollama.ts",
- "./langchain/src/llms/replicate.ts",
- "./langchain/src/llms/fireworks.ts",
- "./langchain/src/llms/googlevertexai/index.ts",
- "./langchain/src/llms/googlevertexai/web.ts",
- "./langchain/src/llms/googlepalm.ts",
- "./langchain/src/llms/gradient_ai.ts",
- "./langchain/src/llms/sagemaker_endpoint.ts",
- "./langchain/src/llms/watsonx_ai.ts",
- "./langchain/src/llms/bedrock/index.ts",
- "./langchain/src/llms/bedrock/web.ts",
- "./langchain/src/llms/llama_cpp.ts",
- "./langchain/src/llms/writer.ts",
- "./langchain/src/llms/portkey.ts",
- "./langchain/src/llms/yandex.ts",
- "./langchain/src/llms/fake.ts",
- "./langchain/src/prompts/index.ts",
- "./langchain/src/prompts/load.ts",
- "./langchain/src/vectorstores/clickhouse.ts",
- "./langchain/src/vectorstores/analyticdb.ts",
- "./langchain/src/vectorstores/base.ts",
- "./langchain/src/vectorstores/cassandra.ts",
- "./langchain/src/vectorstores/convex.ts",
- "./langchain/src/vectorstores/elasticsearch.ts",
- "./langchain/src/vectorstores/memory.ts",
- "./langchain/src/vectorstores/cloudflare_vectorize.ts",
- "./langchain/src/vectorstores/closevector/web.ts",
- "./langchain/src/vectorstores/closevector/node.ts",
- "./langchain/src/vectorstores/chroma.ts",
- "./langchain/src/vectorstores/googlevertexai.ts",
- "./langchain/src/vectorstores/hnswlib.ts",
- "./langchain/src/vectorstores/faiss.ts",
- "./langchain/src/vectorstores/weaviate.ts",
- "./langchain/src/vectorstores/lancedb.ts",
- "./langchain/src/vectorstores/momento_vector_index.ts",
- "./langchain/src/vectorstores/mongo.ts",
- "./langchain/src/vectorstores/mongodb_atlas.ts",
- "./langchain/src/vectorstores/pinecone.ts",
- "./langchain/src/vectorstores/qdrant.ts",
- "./langchain/src/vectorstores/supabase.ts",
- "./langchain/src/vectorstores/opensearch.ts",
- "./langchain/src/vectorstores/pgvector.ts",
- "./langchain/src/vectorstores/milvus.ts",
- "./langchain/src/vectorstores/neo4j_vector.ts",
- "./langchain/src/vectorstores/prisma.ts",
- "./langchain/src/vectorstores/typeorm.ts",
- "./langchain/src/vectorstores/myscale.ts",
- "./langchain/src/vectorstores/redis.ts",
- "./langchain/src/vectorstores/rockset.ts",
- "./langchain/src/vectorstores/typesense.ts",
- "./langchain/src/vectorstores/singlestore.ts",
- "./langchain/src/vectorstores/tigris.ts",
- "./langchain/src/vectorstores/usearch.ts",
- "./langchain/src/vectorstores/vectara.ts",
- "./langchain/src/vectorstores/vercel_postgres.ts",
- "./langchain/src/vectorstores/voy.ts",
- "./langchain/src/vectorstores/xata.ts",
- "./langchain/src/vectorstores/zep.ts",
- "./langchain/src/text_splitter.ts",
- "./langchain/src/memory/index.ts",
- "./langchain/src/memory/zep.ts",
- "./langchain/src/document.ts",
- "./langchain/src/document_loaders/base.ts",
- "./langchain/src/document_loaders/web/apify_dataset.ts",
- "./langchain/src/document_loaders/web/assemblyai.ts",
- "./langchain/src/document_loaders/web/azure_blob_storage_container.ts",
- "./langchain/src/document_loaders/web/azure_blob_storage_file.ts",
- "./langchain/src/document_loaders/web/cheerio.ts",
- "./langchain/src/document_loaders/web/puppeteer.ts",
- "./langchain/src/document_loaders/web/playwright.ts",
- "./langchain/src/document_loaders/web/college_confidential.ts",
- "./langchain/src/document_loaders/web/gitbook.ts",
- "./langchain/src/document_loaders/web/hn.ts",
- "./langchain/src/document_loaders/web/imsdb.ts",
- "./langchain/src/document_loaders/web/figma.ts",
- "./langchain/src/document_loaders/web/github.ts",
- "./langchain/src/document_loaders/web/notiondb.ts",
- "./langchain/src/document_loaders/web/notionapi.ts",
- "./langchain/src/document_loaders/web/pdf.ts",
- "./langchain/src/document_loaders/web/recursive_url.ts",
- "./langchain/src/document_loaders/web/s3.ts",
- "./langchain/src/document_loaders/web/sonix_audio.ts",
- "./langchain/src/document_loaders/web/confluence.ts",
- "./langchain/src/document_loaders/web/searchapi.ts",
- "./langchain/src/document_loaders/web/serpapi.ts",
- "./langchain/src/document_loaders/web/sort_xyz_blockchain.ts",
- "./langchain/src/document_loaders/web/youtube.ts",
- "./langchain/src/document_loaders/fs/directory.ts",
- "./langchain/src/document_loaders/fs/buffer.ts",
- "./langchain/src/document_loaders/fs/chatgpt.ts",
- "./langchain/src/document_loaders/fs/text.ts",
- "./langchain/src/document_loaders/fs/json.ts",
- "./langchain/src/document_loaders/fs/srt.ts",
- "./langchain/src/document_loaders/fs/pdf.ts",
- "./langchain/src/document_loaders/fs/docx.ts",
- "./langchain/src/document_loaders/fs/epub.ts",
- "./langchain/src/document_loaders/fs/csv.ts",
- "./langchain/src/document_loaders/fs/notion.ts",
- "./langchain/src/document_loaders/fs/obsidian.ts",
- "./langchain/src/document_loaders/fs/unstructured.ts",
- "./langchain/src/document_loaders/fs/openai_whisper_audio.ts",
- "./langchain/src/document_loaders/fs/pptx.ts",
- "./langchain/src/document_transformers/html_to_text.ts",
- "./langchain/src/document_transformers/mozilla_readability.ts",
- "./langchain/src/document_transformers/openai_functions.ts",
- "./langchain/src/chat_models/base.ts",
- "./langchain/src/chat_models/openai.ts",
- "./langchain/src/chat_models/portkey.ts",
- "./langchain/src/chat_models/anthropic.ts",
- "./langchain/src/chat_models/bedrock/index.ts",
- "./langchain/src/chat_models/bedrock/web.ts",
- "./langchain/src/chat_models/cloudflare_workersai.ts",
- "./langchain/src/chat_models/googlevertexai/index.ts",
- "./langchain/src/chat_models/googlevertexai/web.ts",
- "./langchain/src/chat_models/googlepalm.ts",
- "./langchain/src/chat_models/fireworks.ts",
- "./langchain/src/chat_models/baiduwenxin.ts",
- "./langchain/src/chat_models/iflytek_xinghuo/index.ts",
- "./langchain/src/chat_models/iflytek_xinghuo/web.ts",
- "./langchain/src/chat_models/ollama.ts",
- "./langchain/src/chat_models/minimax.ts",
- "./langchain/src/chat_models/llama_cpp.ts",
- "./langchain/src/chat_models/yandex.ts",
- "./langchain/src/chat_models/fake.ts",
- "./langchain/src/schema/index.ts",
- "./langchain/src/schema/document.ts",
- "./langchain/src/schema/output_parser.ts",
- "./langchain/src/schema/prompt_template.ts",
- "./langchain/src/schema/query_constructor.ts",
- "./langchain/src/schema/retriever.ts",
- "./langchain/src/schema/runnable/index.ts",
- "./langchain/src/schema/storage.ts",
- "./langchain/src/sql_db.ts",
- "./langchain/src/callbacks/index.ts",
- "./langchain/src/callbacks/handlers/llmonitor.ts",
- "./langchain/src/output_parsers/index.ts",
- "./langchain/src/output_parsers/expression.ts",
- "./langchain/src/retrievers/amazon_kendra.ts",
- "./langchain/src/retrievers/remote/index.ts",
- "./langchain/src/retrievers/supabase.ts",
- "./langchain/src/retrievers/zep.ts",
- "./langchain/src/retrievers/metal.ts",
- "./langchain/src/retrievers/chaindesk.ts",
- "./langchain/src/retrievers/databerry.ts",
- "./langchain/src/retrievers/contextual_compression.ts",
- "./langchain/src/retrievers/document_compressors/index.ts",
- "./langchain/src/retrievers/multi_query.ts",
- "./langchain/src/retrievers/multi_vector.ts",
- "./langchain/src/retrievers/parent_document.ts",
- "./langchain/src/retrievers/tavily_search_api.ts",
- "./langchain/src/retrievers/time_weighted.ts",
- "./langchain/src/retrievers/document_compressors/chain_extract.ts",
- "./langchain/src/retrievers/document_compressors/embeddings_filter.ts",
- "./langchain/src/retrievers/hyde.ts",
- "./langchain/src/retrievers/score_threshold.ts",
- "./langchain/src/retrievers/self_query/index.ts",
- "./langchain/src/retrievers/self_query/chroma.ts",
- "./langchain/src/retrievers/self_query/functional.ts",
- "./langchain/src/retrievers/self_query/pinecone.ts",
- "./langchain/src/retrievers/self_query/supabase.ts",
- "./langchain/src/retrievers/self_query/weaviate.ts",
- "./langchain/src/retrievers/self_query/vectara.ts",
- "./langchain/src/retrievers/vespa.ts",
- "./langchain/src/cache/index.ts",
- "./langchain/src/cache/cloudflare_kv.ts",
- "./langchain/src/cache/momento.ts",
- "./langchain/src/cache/redis.ts",
- "./langchain/src/cache/ioredis.ts",
- "./langchain/src/cache/file_system.ts",
- "./langchain/src/cache/upstash_redis.ts",
- "./langchain/src/stores/doc/in_memory.ts",
- "./langchain/src/stores/doc/gcs.ts",
- "./langchain/src/stores/file/in_memory.ts",
- "./langchain/src/stores/file/node.ts",
- "./langchain/src/stores/message/cassandra.ts",
- "./langchain/src/stores/message/convex.ts",
- "./langchain/src/stores/message/cloudflare_d1.ts",
- "./langchain/src/stores/message/in_memory.ts",
- "./langchain/src/stores/message/dynamodb.ts",
- "./langchain/src/stores/message/firestore.ts",
- "./langchain/src/stores/message/momento.ts",
- "./langchain/src/stores/message/mongodb.ts",
- "./langchain/src/stores/message/redis.ts",
- "./langchain/src/stores/message/ioredis.ts",
- "./langchain/src/stores/message/upstash_redis.ts",
- "./langchain/src/stores/message/planetscale.ts",
- "./langchain/src/stores/message/xata.ts",
- "./langchain/src/storage/convex.ts",
- "./langchain/src/storage/encoder_backed.ts",
- "./langchain/src/storage/in_memory.ts",
- "./langchain/src/storage/ioredis.ts",
- "./langchain/src/storage/vercel_kv.ts",
- "./langchain/src/storage/upstash_redis.ts",
- "./langchain/src/storage/file_system.ts",
- "./langchain/src/graphs/neo4j_graph.ts",
- "./langchain/src/hub.ts",
- "./langchain/src/util/convex.ts",
- "./langchain/src/util/document.ts",
- "./langchain/src/util/math.ts",
- "./langchain/src/util/time.ts",
- "./langchain/src/experimental/autogpt/index.ts",
- "./langchain/src/experimental/openai_assistant/index.ts",
- "./langchain/src/experimental/openai_files/index.ts",
- "./langchain/src/experimental/babyagi/index.ts",
- "./langchain/src/experimental/generative_agents/index.ts",
- "./langchain/src/experimental/plan_and_execute/index.ts",
- "./langchain/src/experimental/multimodal_embeddings/googlevertexai.ts",
- "./langchain/src/experimental/chat_models/anthropic_functions.ts",
- "./langchain/src/experimental/chat_models/bittensor.ts",
- "./langchain/src/experimental/chat_models/ollama_functions.ts",
- "./langchain/src/experimental/llms/bittensor.ts",
- "./langchain/src/experimental/hubs/makersuite/googlemakersuitehub.ts",
- "./langchain/src/experimental/chains/violation_of_expectations/index.ts",
- "./langchain/src/experimental/masking/index.ts",
- "./langchain/src/experimental/tools/pyinterpreter.ts",
- "./langchain/src/evaluation/index.ts",
- "./langchain/src/runnables/index.ts",
- "./langchain/src/runnables/remote.ts"
+ "../../langchain/src/load/index.ts",
+ "../../langchain/src/load/serializable.ts",
+ "../../langchain/src/agents/index.ts",
+ "../../langchain/src/agents/load.ts",
+ "../../langchain/src/agents/toolkits/index.ts",
+ "../../langchain/src/agents/toolkits/aws_sfn.ts",
+ "../../langchain/src/agents/toolkits/connery/index.ts",
+ "../../langchain/src/agents/toolkits/sql/index.ts",
+ "../../langchain/src/agents/format_scratchpad/openai_functions.ts",
+ "../../langchain/src/agents/format_scratchpad/openai_tools.ts",
+ "../../langchain/src/agents/format_scratchpad/log.ts",
+ "../../langchain/src/agents/format_scratchpad/xml.ts",
+ "../../langchain/src/agents/format_scratchpad/log_to_message.ts",
+ "../../langchain/src/agents/react/output_parser.ts",
+ "../../langchain/src/agents/xml/output_parser.ts",
+ "../../langchain/src/agents/openai/output_parser.ts",
+ "../../langchain/src/base_language/index.ts",
+ "../../langchain/src/tools/index.ts",
+ "../../langchain/src/tools/aws_lambda.ts",
+ "../../langchain/src/tools/aws_sfn.ts",
+ "../../langchain/src/tools/calculator.ts",
+ "../../langchain/src/tools/connery.ts",
+ "../../langchain/src/tools/render.ts",
+ "../../langchain/src/tools/sql.ts",
+ "../../langchain/src/tools/webbrowser.ts",
+ "../../langchain/src/tools/gmail/index.ts",
+ "../../langchain/src/tools/google_calendar/index.ts",
+ "../../langchain/src/tools/google_places.ts",
+ "../../langchain/src/chains/index.ts",
+ "../../langchain/src/chains/combine_documents/reduce.ts",
+ "../../langchain/src/chains/load.ts",
+ "../../langchain/src/chains/openai_functions/index.ts",
+ "../../langchain/src/chains/query_constructor/index.ts",
+ "../../langchain/src/chains/query_constructor/ir.ts",
+ "../../langchain/src/chains/sql_db/index.ts",
+ "../../langchain/src/chains/graph_qa/cypher.ts",
+ "../../langchain/src/embeddings/base.ts",
+ "../../langchain/src/embeddings/bedrock.ts",
+ "../../langchain/src/embeddings/cache_backed.ts",
+ "../../langchain/src/embeddings/cloudflare_workersai.ts",
+ "../../langchain/src/embeddings/fake.ts",
+ "../../langchain/src/embeddings/ollama.ts",
+ "../../langchain/src/embeddings/openai.ts",
+ "../../langchain/src/embeddings/cohere.ts",
+ "../../langchain/src/embeddings/tensorflow.ts",
+ "../../langchain/src/embeddings/hf.ts",
+ "../../langchain/src/embeddings/hf_transformers.ts",
+ "../../langchain/src/embeddings/googlevertexai.ts",
+ "../../langchain/src/embeddings/googlepalm.ts",
+ "../../langchain/src/embeddings/minimax.ts",
+ "../../langchain/src/embeddings/voyage.ts",
+ "../../langchain/src/embeddings/llama_cpp.ts",
+ "../../langchain/src/embeddings/gradient_ai.ts",
+ "../../langchain/src/llms/load.ts",
+ "../../langchain/src/llms/base.ts",
+ "../../langchain/src/llms/openai.ts",
+ "../../langchain/src/llms/ai21.ts",
+ "../../langchain/src/llms/aleph_alpha.ts",
+ "../../langchain/src/llms/cloudflare_workersai.ts",
+ "../../langchain/src/llms/cohere.ts",
+ "../../langchain/src/llms/hf.ts",
+ "../../langchain/src/llms/raycast.ts",
+ "../../langchain/src/llms/ollama.ts",
+ "../../langchain/src/llms/replicate.ts",
+ "../../langchain/src/llms/fireworks.ts",
+ "../../langchain/src/llms/googlevertexai/index.ts",
+ "../../langchain/src/llms/googlevertexai/web.ts",
+ "../../langchain/src/llms/googlepalm.ts",
+ "../../langchain/src/llms/gradient_ai.ts",
+ "../../langchain/src/llms/sagemaker_endpoint.ts",
+ "../../langchain/src/llms/watsonx_ai.ts",
+ "../../langchain/src/llms/bedrock/index.ts",
+ "../../langchain/src/llms/bedrock/web.ts",
+ "../../langchain/src/llms/llama_cpp.ts",
+ "../../langchain/src/llms/writer.ts",
+ "../../langchain/src/llms/portkey.ts",
+ "../../langchain/src/llms/yandex.ts",
+ "../../langchain/src/llms/fake.ts",
+ "../../langchain/src/prompts/index.ts",
+ "../../langchain/src/prompts/load.ts",
+ "../../langchain/src/vectorstores/clickhouse.ts",
+ "../../langchain/src/vectorstores/analyticdb.ts",
+ "../../langchain/src/vectorstores/base.ts",
+ "../../langchain/src/vectorstores/cassandra.ts",
+ "../../langchain/src/vectorstores/convex.ts",
+ "../../langchain/src/vectorstores/elasticsearch.ts",
+ "../../langchain/src/vectorstores/memory.ts",
+ "../../langchain/src/vectorstores/cloudflare_vectorize.ts",
+ "../../langchain/src/vectorstores/closevector/web.ts",
+ "../../langchain/src/vectorstores/closevector/node.ts",
+ "../../langchain/src/vectorstores/chroma.ts",
+ "../../langchain/src/vectorstores/googlevertexai.ts",
+ "../../langchain/src/vectorstores/hnswlib.ts",
+ "../../langchain/src/vectorstores/faiss.ts",
+ "../../langchain/src/vectorstores/weaviate.ts",
+ "../../langchain/src/vectorstores/lancedb.ts",
+ "../../langchain/src/vectorstores/momento_vector_index.ts",
+ "../../langchain/src/vectorstores/mongo.ts",
+ "../../langchain/src/vectorstores/mongodb_atlas.ts",
+ "../../langchain/src/vectorstores/pinecone.ts",
+ "../../langchain/src/vectorstores/qdrant.ts",
+ "../../langchain/src/vectorstores/supabase.ts",
+ "../../langchain/src/vectorstores/opensearch.ts",
+ "../../langchain/src/vectorstores/pgvector.ts",
+ "../../langchain/src/vectorstores/milvus.ts",
+ "../../langchain/src/vectorstores/neo4j_vector.ts",
+ "../../langchain/src/vectorstores/prisma.ts",
+ "../../langchain/src/vectorstores/typeorm.ts",
+ "../../langchain/src/vectorstores/myscale.ts",
+ "../../langchain/src/vectorstores/redis.ts",
+ "../../langchain/src/vectorstores/rockset.ts",
+ "../../langchain/src/vectorstores/typesense.ts",
+ "../../langchain/src/vectorstores/singlestore.ts",
+ "../../langchain/src/vectorstores/tigris.ts",
+ "../../langchain/src/vectorstores/usearch.ts",
+ "../../langchain/src/vectorstores/vectara.ts",
+ "../../langchain/src/vectorstores/vercel_postgres.ts",
+ "../../langchain/src/vectorstores/voy.ts",
+ "../../langchain/src/vectorstores/xata.ts",
+ "../../langchain/src/vectorstores/zep.ts",
+ "../../langchain/src/text_splitter.ts",
+ "../../langchain/src/memory/index.ts",
+ "../../langchain/src/memory/zep.ts",
+ "../../langchain/src/document.ts",
+ "../../langchain/src/document_loaders/base.ts",
+ "../../langchain/src/document_loaders/web/apify_dataset.ts",
+ "../../langchain/src/document_loaders/web/assemblyai.ts",
+ "../../langchain/src/document_loaders/web/azure_blob_storage_container.ts",
+ "../../langchain/src/document_loaders/web/azure_blob_storage_file.ts",
+ "../../langchain/src/document_loaders/web/cheerio.ts",
+ "../../langchain/src/document_loaders/web/puppeteer.ts",
+ "../../langchain/src/document_loaders/web/playwright.ts",
+ "../../langchain/src/document_loaders/web/college_confidential.ts",
+ "../../langchain/src/document_loaders/web/gitbook.ts",
+ "../../langchain/src/document_loaders/web/hn.ts",
+ "../../langchain/src/document_loaders/web/imsdb.ts",
+ "../../langchain/src/document_loaders/web/figma.ts",
+ "../../langchain/src/document_loaders/web/github.ts",
+ "../../langchain/src/document_loaders/web/notiondb.ts",
+ "../../langchain/src/document_loaders/web/notionapi.ts",
+ "../../langchain/src/document_loaders/web/pdf.ts",
+ "../../langchain/src/document_loaders/web/recursive_url.ts",
+ "../../langchain/src/document_loaders/web/s3.ts",
+ "../../langchain/src/document_loaders/web/sonix_audio.ts",
+ "../../langchain/src/document_loaders/web/confluence.ts",
+ "../../langchain/src/document_loaders/web/searchapi.ts",
+ "../../langchain/src/document_loaders/web/serpapi.ts",
+ "../../langchain/src/document_loaders/web/sort_xyz_blockchain.ts",
+ "../../langchain/src/document_loaders/web/youtube.ts",
+ "../../langchain/src/document_loaders/fs/directory.ts",
+ "../../langchain/src/document_loaders/fs/buffer.ts",
+ "../../langchain/src/document_loaders/fs/chatgpt.ts",
+ "../../langchain/src/document_loaders/fs/text.ts",
+ "../../langchain/src/document_loaders/fs/json.ts",
+ "../../langchain/src/document_loaders/fs/srt.ts",
+ "../../langchain/src/document_loaders/fs/pdf.ts",
+ "../../langchain/src/document_loaders/fs/docx.ts",
+ "../../langchain/src/document_loaders/fs/epub.ts",
+ "../../langchain/src/document_loaders/fs/csv.ts",
+ "../../langchain/src/document_loaders/fs/notion.ts",
+ "../../langchain/src/document_loaders/fs/obsidian.ts",
+ "../../langchain/src/document_loaders/fs/unstructured.ts",
+ "../../langchain/src/document_loaders/fs/openai_whisper_audio.ts",
+ "../../langchain/src/document_loaders/fs/pptx.ts",
+ "../../langchain/src/document_transformers/html_to_text.ts",
+ "../../langchain/src/document_transformers/mozilla_readability.ts",
+ "../../langchain/src/document_transformers/openai_functions.ts",
+ "../../langchain/src/chat_models/base.ts",
+ "../../langchain/src/chat_models/openai.ts",
+ "../../langchain/src/chat_models/portkey.ts",
+ "../../langchain/src/chat_models/anthropic.ts",
+ "../../langchain/src/chat_models/bedrock/index.ts",
+ "../../langchain/src/chat_models/bedrock/web.ts",
+ "../../langchain/src/chat_models/cloudflare_workersai.ts",
+ "../../langchain/src/chat_models/googlevertexai/index.ts",
+ "../../langchain/src/chat_models/googlevertexai/web.ts",
+ "../../langchain/src/chat_models/googlepalm.ts",
+ "../../langchain/src/chat_models/fireworks.ts",
+ "../../langchain/src/chat_models/baiduwenxin.ts",
+ "../../langchain/src/chat_models/iflytek_xinghuo/index.ts",
+ "../../langchain/src/chat_models/iflytek_xinghuo/web.ts",
+ "../../langchain/src/chat_models/ollama.ts",
+ "../../langchain/src/chat_models/minimax.ts",
+ "../../langchain/src/chat_models/llama_cpp.ts",
+ "../../langchain/src/chat_models/yandex.ts",
+ "../../langchain/src/chat_models/fake.ts",
+ "../../langchain/src/schema/index.ts",
+ "../../langchain/src/schema/document.ts",
+ "../../langchain/src/schema/output_parser.ts",
+ "../../langchain/src/schema/prompt_template.ts",
+ "../../langchain/src/schema/query_constructor.ts",
+ "../../langchain/src/schema/retriever.ts",
+ "../../langchain/src/schema/runnable/index.ts",
+ "../../langchain/src/schema/storage.ts",
+ "../../langchain/src/sql_db.ts",
+ "../../langchain/src/callbacks/index.ts",
+ "../../langchain/src/callbacks/handlers/llmonitor.ts",
+ "../../langchain/src/output_parsers/index.ts",
+ "../../langchain/src/output_parsers/expression.ts",
+ "../../langchain/src/retrievers/amazon_kendra.ts",
+ "../../langchain/src/retrievers/remote/index.ts",
+ "../../langchain/src/retrievers/supabase.ts",
+ "../../langchain/src/retrievers/zep.ts",
+ "../../langchain/src/retrievers/metal.ts",
+ "../../langchain/src/retrievers/chaindesk.ts",
+ "../../langchain/src/retrievers/databerry.ts",
+ "../../langchain/src/retrievers/contextual_compression.ts",
+ "../../langchain/src/retrievers/document_compressors/index.ts",
+ "../../langchain/src/retrievers/multi_query.ts",
+ "../../langchain/src/retrievers/multi_vector.ts",
+ "../../langchain/src/retrievers/parent_document.ts",
+ "../../langchain/src/retrievers/tavily_search_api.ts",
+ "../../langchain/src/retrievers/time_weighted.ts",
+ "../../langchain/src/retrievers/document_compressors/chain_extract.ts",
+ "../../langchain/src/retrievers/document_compressors/embeddings_filter.ts",
+ "../../langchain/src/retrievers/hyde.ts",
+ "../../langchain/src/retrievers/score_threshold.ts",
+ "../../langchain/src/retrievers/self_query/index.ts",
+ "../../langchain/src/retrievers/self_query/chroma.ts",
+ "../../langchain/src/retrievers/self_query/functional.ts",
+ "../../langchain/src/retrievers/self_query/pinecone.ts",
+ "../../langchain/src/retrievers/self_query/supabase.ts",
+ "../../langchain/src/retrievers/self_query/weaviate.ts",
+ "../../langchain/src/retrievers/self_query/vectara.ts",
+ "../../langchain/src/retrievers/vespa.ts",
+ "../../langchain/src/cache/index.ts",
+ "../../langchain/src/cache/cloudflare_kv.ts",
+ "../../langchain/src/cache/momento.ts",
+ "../../langchain/src/cache/redis.ts",
+ "../../langchain/src/cache/ioredis.ts",
+ "../../langchain/src/cache/file_system.ts",
+ "../../langchain/src/cache/upstash_redis.ts",
+ "../../langchain/src/stores/doc/in_memory.ts",
+ "../../langchain/src/stores/doc/gcs.ts",
+ "../../langchain/src/stores/file/in_memory.ts",
+ "../../langchain/src/stores/file/node.ts",
+ "../../langchain/src/stores/message/cassandra.ts",
+ "../../langchain/src/stores/message/convex.ts",
+ "../../langchain/src/stores/message/cloudflare_d1.ts",
+ "../../langchain/src/stores/message/in_memory.ts",
+ "../../langchain/src/stores/message/dynamodb.ts",
+ "../../langchain/src/stores/message/firestore.ts",
+ "../../langchain/src/stores/message/momento.ts",
+ "../../langchain/src/stores/message/mongodb.ts",
+ "../../langchain/src/stores/message/redis.ts",
+ "../../langchain/src/stores/message/ioredis.ts",
+ "../../langchain/src/stores/message/upstash_redis.ts",
+ "../../langchain/src/stores/message/planetscale.ts",
+ "../../langchain/src/stores/message/xata.ts",
+ "../../langchain/src/storage/convex.ts",
+ "../../langchain/src/storage/encoder_backed.ts",
+ "../../langchain/src/storage/in_memory.ts",
+ "../../langchain/src/storage/ioredis.ts",
+ "../../langchain/src/storage/vercel_kv.ts",
+ "../../langchain/src/storage/upstash_redis.ts",
+ "../../langchain/src/storage/file_system.ts",
+ "../../langchain/src/graphs/neo4j_graph.ts",
+ "../../langchain/src/hub.ts",
+ "../../langchain/src/util/convex.ts",
+ "../../langchain/src/util/document.ts",
+ "../../langchain/src/util/math.ts",
+ "../../langchain/src/util/time.ts",
+ "../../langchain/src/experimental/autogpt/index.ts",
+ "../../langchain/src/experimental/openai_assistant/index.ts",
+ "../../langchain/src/experimental/openai_files/index.ts",
+ "../../langchain/src/experimental/babyagi/index.ts",
+ "../../langchain/src/experimental/generative_agents/index.ts",
+ "../../langchain/src/experimental/plan_and_execute/index.ts",
+ "../../langchain/src/experimental/multimodal_embeddings/googlevertexai.ts",
+ "../../langchain/src/experimental/chat_models/anthropic_functions.ts",
+ "../../langchain/src/experimental/chat_models/bittensor.ts",
+ "../../langchain/src/experimental/chat_models/ollama_functions.ts",
+ "../../langchain/src/experimental/llms/bittensor.ts",
+ "../../langchain/src/experimental/hubs/makersuite/googlemakersuitehub.ts",
+ "../../langchain/src/experimental/chains/violation_of_expectations/index.ts",
+ "../../langchain/src/experimental/masking/index.ts",
+ "../../langchain/src/experimental/tools/pyinterpreter.ts",
+ "../../langchain/src/evaluation/index.ts",
+ "../../langchain/src/runnables/index.ts",
+ "../../langchain/src/runnables/remote.ts"
]
}
diff --git a/docs/api_refs/typedoc_plugins/hide_underscore_lc.js b/docs/api_refs/typedoc_plugins/hide_underscore_lc.js
new file mode 100644
index 000000000000..c8f5e186e6d7
--- /dev/null
+++ b/docs/api_refs/typedoc_plugins/hide_underscore_lc.js
@@ -0,0 +1,70 @@
+const {
+ Application,
+ Converter,
+ Context,
+ ReflectionKind,
+ DeclarationReflection,
+} = require("typedoc");
+
+/**
+ * @param {Application} application
+ * @returns {void}
+ */
+function load(application) {
+ /**
+ * @type {Array}
+ */
+ let reflectionsToHide = [];
+
+ application.converter.on(
+ Converter.EVENT_CREATE_DECLARATION,
+ resolveReflection
+ );
+ application.converter.on(Converter.EVENT_RESOLVE_BEGIN, onBeginResolve);
+
+ const reflectionKindsToHide = [
+ ReflectionKind.Property,
+ ReflectionKind.Accessor,
+ ReflectionKind.Variable,
+ ReflectionKind.Method,
+ ReflectionKind.Function,
+ ReflectionKind.Class,
+ ReflectionKind.Interface,
+ ReflectionKind.Enum,
+ ReflectionKind.TypeAlias,
+ ];
+
+ /**
+ * @param {Context} context
+ * @returns {void}
+ */
+ function onBeginResolve(context) {
+ reflectionsToHide.forEach((reflection) => {
+ const { project } = context;
+ // Remove the property from documentation
+ project.removeReflection(reflection);
+ });
+ }
+
+ /**
+ * @param {Context} _context
+ * @param {DeclarationReflection} reflection
+ * @returns {void}
+ */
+ function resolveReflection(
+ _context,
+ reflection
+ ) {
+ const reflectionKind = reflection.kind;
+ if (reflectionKindsToHide.includes(reflectionKind)) {
+ if (
+ reflection.name.startsWith("_") ||
+ reflection.name.startsWith("lc_")
+ ) {
+ reflectionsToHide.push(reflection);
+ }
+ }
+ }
+}
+
+module.exports = { load };
diff --git a/docs/core_docs/docs/integrations/tools/discord.mdx b/docs/core_docs/docs/integrations/tools/discord.mdx
new file mode 100644
index 000000000000..476d44c99172
--- /dev/null
+++ b/docs/core_docs/docs/integrations/tools/discord.mdx
@@ -0,0 +1,30 @@
+---
+hide_table_of_contents: true
+---
+
+import CodeBlock from "@theme/CodeBlock";
+
+# Discord Tool
+
+The Discord Tool gives your agent the ability to search, read, and write messages to discord channels.
+It is useful for when you need to interact with a discord channel.
+
+## Setup
+
+To use the Discord Tool you need to install the following official peer depencency:
+
+```bash npm2yarn
+npm install discord.js
+```
+
+## Usage, standalone
+
+import ToolExample from "@examples/tools/discord.ts";
+
+{ToolExample}
+
+## Usage, in an Agent
+
+import AgentExample from "@examples/agents/discord.ts";
+
+{AgentExample}
diff --git a/docs/core_docs/package.json b/docs/core_docs/package.json
index bd7067f7ba8e..fcb86dda8dc1 100644
--- a/docs/core_docs/package.json
+++ b/docs/core_docs/package.json
@@ -5,8 +5,10 @@
"scripts": {
"docusaurus": "docusaurus",
"start": "yarn build:typedoc && rimraf ./docs/api && NODE_OPTIONS=--max-old-space-size=7168 docusaurus start",
- "build": "yarn build:typedoc && rimraf ./build && NODE_OPTIONS=--max-old-space-size=7168 DOCUSAURUS_SSR_CONCURRENCY=4 docusaurus build",
- "build:typedoc": "cd ../api_refs && yarn build",
+ "build": "yarn clean && yarn build:typedoc && rimraf ./build && NODE_OPTIONS=--max-old-space-size=7168 DOCUSAURUS_SSR_CONCURRENCY=4 docusaurus build",
+ "build:vercel": "yarn clean && yarn build:typedoc:vercel && rimraf ./build && NODE_OPTIONS=--max-old-space-size=7168 DOCUSAURUS_SSR_CONCURRENCY=4 docusaurus build",
+ "build:typedoc": "yarn run turbo:command build --filter=api_refs",
+ "build:typedoc:vercel": "yarn workspace api_refs build:vercel",
"swizzle": "docusaurus swizzle",
"deploy": "docusaurus deploy",
"clear": "docusaurus clear",
@@ -17,7 +19,8 @@
"lint:fix": "yarn lint --fix",
"precommit": "lint-staged",
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,md,mdx}\"",
- "format:check": "prettier --check \"**/*.{js,jsx,ts,tsx,md,mdx}\""
+ "format:check": "prettier --check \"**/*.{js,jsx,ts,tsx,md,mdx}\"",
+ "clean": "rm -rf .docusaurus/ .turbo/ .build/"
},
"dependencies": {
"@docusaurus/core": "2.4.3",
diff --git a/environment_tests/scripts/docker-ci-entrypoint.sh b/environment_tests/scripts/docker-ci-entrypoint.sh
index dd98d4276256..174d8ba311cd 100644
--- a/environment_tests/scripts/docker-ci-entrypoint.sh
+++ b/environment_tests/scripts/docker-ci-entrypoint.sh
@@ -10,20 +10,25 @@ shopt -s extglob
# avoid copying build artifacts from the host
cp -r ../package/!(node_modules|dist|dist-cjs|dist-esm|build|.next|.turbo) .
+mkdir -p ./libs/langchain-core/
+mkdir -p ./libs/langchain-openai/
+mkdir -p ./libs/langchain-anthropic/
+mkdir -p ./libs/langchain-community/
+mkdir -p ./libs/langchain/
+
+cp -r ../langchain-core ./libs/
+cp -r ../langchain-openai ./libs/
+cp -r ../langchain-anthropic ./libs/
+cp -r ../langchain-community ./libs/
+cp -r ../langchain ./libs/
+
# copy cache
mkdir -p ./.yarn
cp -r ../root/.yarn/!(berry|cache) ./.yarn
cp ../root/yarn.lock ../root/.yarnrc.yml .
-# Replace the workspace dependency with the local copy, and install all others
-# Avoid calling "yarn add ../langchain" as yarn berry does seem to hang for ~30s
-# before installation actually occurs
-sed -i 's/"@langchain\/core": "workspace:\*"/"@langchain\/core": "..\/langchain-core"/g' package.json
-sed -i 's/"@langchain\/anthropic": "workspace:\*"/"@langchain\/anthropic": "..\/langchain-anthropic"/g' package.json
-sed -i 's/"@langchain\/openai": "workspace:\*"/"@langchain\/openai": "..\/langchain-openai"/g' package.json
-sed -i 's/"langchain": "workspace:\*"/"langchain": "..\/langchain"/g' package.json
-
-yarn install --no-immutable
+yarn plugin import workspace-tools
+yarn workspaces focus --production
# Check the build command completes successfully
yarn build
diff --git a/environment_tests/test-exports-bun/package.json b/environment_tests/test-exports-bun/package.json
index 8294ac754257..649c5e7a1f3d 100644
--- a/environment_tests/test-exports-bun/package.json
+++ b/environment_tests/test-exports-bun/package.json
@@ -18,6 +18,7 @@
"license": "MIT",
"dependencies": {
"@langchain/anthropic": "workspace:*",
+ "@langchain/community": "workspace:*",
"@langchain/core": "workspace:*",
"@langchain/openai": "workspace:*",
"d3-dsv": "2",
diff --git a/environment_tests/test-exports-cf/package.json b/environment_tests/test-exports-cf/package.json
index b87c55713fda..6b892dde4870 100644
--- a/environment_tests/test-exports-cf/package.json
+++ b/environment_tests/test-exports-cf/package.json
@@ -1,17 +1,21 @@
{
"name": "test-exports-cf",
"version": "0.0.0",
+ "workspaces": [
+ "libs/*"
+ ],
"devDependencies": {
- "@cloudflare/workers-types": "^4.20230321.0",
- "typescript": "^5.0.3",
- "vitest": "0.34.3",
- "wrangler": "3.7.0"
+ "@cloudflare/workers-types": "^4.20230321.0"
},
"dependencies": {
"@langchain/anthropic": "workspace:*",
+ "@langchain/community": "workspace:*",
"@langchain/core": "workspace:*",
"@langchain/openai": "workspace:*",
- "langchain": "workspace:*"
+ "langchain": "workspace:*",
+ "wrangler": "3.7.0",
+ "vitest": "0.34.3",
+ "typescript": "^5.0.3"
},
"private": true,
"scripts": {
diff --git a/environment_tests/test-exports-cjs/package.json b/environment_tests/test-exports-cjs/package.json
index b0b43151e2b4..44c4d0fa3e44 100644
--- a/environment_tests/test-exports-cjs/package.json
+++ b/environment_tests/test-exports-cjs/package.json
@@ -1,6 +1,9 @@
{
"name": "test-exports-cjs",
"version": "0.0.0",
+ "workspaces": [
+ "libs/*"
+ ],
"private": true,
"description": "CJS Tests for the things exported by the langchain package",
"main": "./index.mjs",
@@ -19,16 +22,17 @@
"license": "MIT",
"dependencies": {
"@langchain/anthropic": "workspace:*",
+ "@langchain/community": "workspace:*",
"@langchain/core": "workspace:*",
"@langchain/openai": "workspace:*",
+ "@tsconfig/recommended": "^1.0.2",
"d3-dsv": "2",
"hnswlib-node": "^1.4.2",
- "langchain": "workspace:*"
+ "langchain": "workspace:*",
+ "typescript": "^5.0.0"
},
"devDependencies": {
- "@tsconfig/recommended": "^1.0.2",
"@types/node": "^18.15.11",
- "prettier": "^2.8.3",
- "typescript": "^5.0.0"
+ "prettier": "^2.8.3"
}
}
diff --git a/environment_tests/test-exports-esbuild/package.json b/environment_tests/test-exports-esbuild/package.json
index 15241cd5ef20..3a099de0303d 100644
--- a/environment_tests/test-exports-esbuild/package.json
+++ b/environment_tests/test-exports-esbuild/package.json
@@ -1,6 +1,9 @@
{
"name": "test-exports-esbuild",
"version": "0.0.0",
+ "workspaces": [
+ "libs/*"
+ ],
"private": true,
"description": "Tests for the things exported by the langchain package",
"main": "./index.mjs",
@@ -17,17 +20,18 @@
"license": "MIT",
"dependencies": {
"@langchain/anthropic": "workspace:*",
+ "@langchain/community": "workspace:*",
"@langchain/core": "workspace:*",
"@langchain/openai": "workspace:*",
+ "@tsconfig/recommended": "^1.0.2",
"d3-dsv": "2",
+ "esbuild": "^0.17.18",
"hnswlib-node": "^1.4.2",
- "langchain": "workspace:*"
+ "langchain": "workspace:*",
+ "typescript": "^5.0.0"
},
"devDependencies": {
- "@tsconfig/recommended": "^1.0.2",
"@types/node": "^18.15.11",
- "esbuild": "^0.17.18",
- "prettier": "^2.8.3",
- "typescript": "^5.0.0"
+ "prettier": "^2.8.3"
}
}
diff --git a/environment_tests/test-exports-esm/package.json b/environment_tests/test-exports-esm/package.json
index a79fc8e8b174..f93b3d97be16 100644
--- a/environment_tests/test-exports-esm/package.json
+++ b/environment_tests/test-exports-esm/package.json
@@ -1,6 +1,9 @@
{
"name": "test-exports-esm",
"version": "0.0.0",
+ "workspaces": [
+ "libs/*"
+ ],
"private": true,
"description": "Tests for the things exported by the langchain package",
"main": "./index.mjs",
@@ -20,16 +23,17 @@
"license": "MIT",
"dependencies": {
"@langchain/anthropic": "workspace:*",
+ "@langchain/community": "workspace:*",
"@langchain/core": "workspace:*",
"@langchain/openai": "workspace:*",
+ "@tsconfig/recommended": "^1.0.2",
"d3-dsv": "2",
"hnswlib-node": "^1.4.2",
- "langchain": "workspace:*"
+ "langchain": "workspace:*",
+ "typescript": "^5.0.0"
},
"devDependencies": {
- "@tsconfig/recommended": "^1.0.2",
"@types/node": "^18.15.11",
- "prettier": "^2.8.3",
- "typescript": "^5.0.0"
+ "prettier": "^2.8.3"
}
}
diff --git a/environment_tests/test-exports-vercel/package.json b/environment_tests/test-exports-vercel/package.json
index c784c3d21a8d..c3adfd63ac3e 100644
--- a/environment_tests/test-exports-vercel/package.json
+++ b/environment_tests/test-exports-vercel/package.json
@@ -1,6 +1,9 @@
{
"name": "test-exports-vercel",
"version": "0.1.0",
+ "workspaces": [
+ "libs/*"
+ ],
"private": true,
"scripts": {
"dev": "next dev",
@@ -10,6 +13,7 @@
},
"dependencies": {
"@langchain/anthropic": "workspace:*",
+ "@langchain/community": "workspace:*",
"@langchain/core": "workspace:*",
"@langchain/openai": "workspace:*",
"@types/node": "18.15.11",
diff --git a/environment_tests/test-exports-vercel/tsconfig.json b/environment_tests/test-exports-vercel/tsconfig.json
index b4d71bd310b5..01af0ac31dac 100644
--- a/environment_tests/test-exports-vercel/tsconfig.json
+++ b/environment_tests/test-exports-vercel/tsconfig.json
@@ -20,5 +20,8 @@
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
- "exclude": ["node_modules"]
+ "exclude": [
+ "node_modules",
+ "libs"
+ ]
}
diff --git a/environment_tests/test-exports-vite/package.json b/environment_tests/test-exports-vite/package.json
index 3a3ea14886d5..178d95a49ead 100644
--- a/environment_tests/test-exports-vite/package.json
+++ b/environment_tests/test-exports-vite/package.json
@@ -1,7 +1,10 @@
{
"name": "test-exports-vite",
- "private": true,
"version": "0.0.0",
+ "workspaces": [
+ "libs/*"
+ ],
+ "private": true,
"type": "module",
"scripts": {
"dev": "vite",
@@ -11,11 +14,10 @@
},
"dependencies": {
"@langchain/anthropic": "workspace:*",
+ "@langchain/community": "workspace:*",
"@langchain/core": "workspace:*",
"@langchain/openai": "workspace:*",
- "langchain": "workspace:*"
- },
- "devDependencies": {
+ "langchain": "workspace:*",
"typescript": "^5.0.0",
"vite": "^4.2.0"
}
diff --git a/examples/package.json b/examples/package.json
index bbc292a7a930..477068885925 100644
--- a/examples/package.json
+++ b/examples/package.json
@@ -27,6 +27,7 @@
"@getmetal/metal-sdk": "^4.0.0",
"@getzep/zep-js": "^0.9.0",
"@gomomento/sdk": "^1.51.1",
+ "@langchain/community": "workspace:*",
"@opensearch-project/opensearch": "^2.2.0",
"@pinecone-database/pinecone": "^1.1.0",
"@planetscale/database": "^1.8.0",
diff --git a/examples/src/agents/discord.ts b/examples/src/agents/discord.ts
new file mode 100644
index 000000000000..658c0b6a86db
--- /dev/null
+++ b/examples/src/agents/discord.ts
@@ -0,0 +1,22 @@
+import { ChatOpenAI } from "langchain/chat_models/openai";
+import { initializeAgentExecutorWithOptions } from "langchain/agents";
+import { DadJokeAPI } from "langchain/tools";
+import { DiscordSendMessagesTool } from "@langchain/community/tools/discord";
+
+const model = new ChatOpenAI({
+ temperature: 0,
+});
+
+const tools = [new DiscordSendMessagesTool(), new DadJokeAPI()];
+
+const executor = await initializeAgentExecutorWithOptions(tools, model, {
+ agentType: "zero-shot-react-description",
+ verbose: true,
+});
+
+const res = await executor.call({
+ input: `Tell a joke in the discord channel`,
+});
+
+console.log(res.output);
+// "What's the best thing about elevator jokes? They work on so many levels."
diff --git a/examples/src/guides/expression_language/runnable_history.ts b/examples/src/guides/expression_language/runnable_history.ts
index afcd7aade6c2..0d3130e07ff2 100644
--- a/examples/src/guides/expression_language/runnable_history.ts
+++ b/examples/src/guides/expression_language/runnable_history.ts
@@ -1,5 +1,5 @@
import { ChatOpenAI } from "langchain/chat_models/openai";
-import { ChatMessageHistory } from "langchain/stores/message/in_memory";
+import { ChatMessageHistory } from "langchain/memory";
import { ChatPromptTemplate, MessagesPlaceholder } from "langchain/prompts";
import {
RunnableConfig,
diff --git a/examples/src/guides/expression_language/runnable_history_constructor_config.ts b/examples/src/guides/expression_language/runnable_history_constructor_config.ts
index 55405ccd95c5..b04f614ec22e 100644
--- a/examples/src/guides/expression_language/runnable_history_constructor_config.ts
+++ b/examples/src/guides/expression_language/runnable_history_constructor_config.ts
@@ -1,5 +1,5 @@
import { ChatOpenAI } from "langchain/chat_models/openai";
-import { ChatMessageHistory } from "langchain/stores/message/in_memory";
+import { ChatMessageHistory } from "langchain/memory";
import { ChatPromptTemplate, MessagesPlaceholder } from "langchain/prompts";
import {
RunnableConfig,
diff --git a/examples/src/tools/discord.ts b/examples/src/tools/discord.ts
new file mode 100644
index 000000000000..b54e0046adc8
--- /dev/null
+++ b/examples/src/tools/discord.ts
@@ -0,0 +1,32 @@
+import {
+ DiscordGetMessagesTool,
+ DiscordChannelSearchTool,
+ DiscordSendMessagesTool,
+ DiscordGetGuildsTool,
+ DiscordGetTextChannelsTool,
+} from "@langchain/community/tools/discord";
+
+// Get messages from a channel given channel ID
+const getMessageTool = new DiscordGetMessagesTool();
+const messageResults = await getMessageTool.invoke("1153400523718938780");
+console.log(messageResults);
+
+// Get guilds/servers
+const getGuildsTool = new DiscordGetGuildsTool();
+const guildResults = await getGuildsTool.invoke("");
+console.log(guildResults);
+
+// Search results in a given channel (case-insensitive)
+const searchTool = new DiscordChannelSearchTool();
+const searchResults = await searchTool.invoke("Test");
+console.log(searchResults);
+
+// Get all text channels of a server
+const getChannelsTool = new DiscordGetTextChannelsTool();
+const channelResults = await getChannelsTool.invoke("1153400523718938775");
+console.log(channelResults);
+
+// Send a message
+const sendMessageTool = new DiscordSendMessagesTool();
+const sendMessageResults = await sendMessageTool.invoke("test message");
+console.log(sendMessageResults);
diff --git a/langchain-core/.gitignore b/langchain-core/.gitignore
index 05ba9919a328..c6100ae28393 100644
--- a/langchain-core/.gitignore
+++ b/langchain-core/.gitignore
@@ -106,6 +106,9 @@ utils/json_patch.d.ts
utils/json_schema.cjs
utils/json_schema.js
utils/json_schema.d.ts
+utils/math.cjs
+utils/math.js
+utils/math.d.ts
utils/stream.cjs
utils/stream.js
utils/stream.d.ts
diff --git a/langchain-core/README.md b/langchain-core/README.md
index c69646b77823..d885a1acddc1 100644
--- a/langchain-core/README.md
+++ b/langchain-core/README.md
@@ -1,21 +1,24 @@
-# 🦜️🔗 @langchain/core
+# 🦜🍎️ @langchain/core
-:::note
-This package is experimental at the moment and may change.
-:::
+[![CI](https://github.com/langchain-ai/langchainjs/actions/workflows/ci.yml/badge.svg)](https://github.com/langchain-ai/langchainjs/actions/workflows/ci.yml) ![npm](https://img.shields.io/npm/dw/@langchain/core) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Twitter](https://img.shields.io/twitter/url/https/twitter.com/langchainai.svg?style=social&label=Follow%20%40LangChainAI)](https://twitter.com/langchainai) [![](https://dcbadge.vercel.app/api/server/6adMQxSpJS?compact=true&style=flat)](https://discord.gg/6adMQxSpJS)
`@langchain/core` contains the core abstractions and schemas of LangChain.js, including base classes for language models,
chat models, vectorstores, retrievers, and runnables.
-## 🔧 Usage
-
-Install core like this:
+## 💾 Quick Install
```bash
$ yarn add @langchain/core
```
-Then, you can install other provider-specific packages like this:
+## 🤔 What is this?
+
+`@langchain/core` contains the base abstractions that power the rest of the LangChain ecosystem.
+These abstractions are designed to be as modular and simple as possible.
+Examples of these abstractions include those for language models, document loaders, embedding models, vectorstores, retrievers, and more.
+The benefit of having these abstractions is that any provider can implement the required interface and then easily be used in the rest of the LangChain ecosystem.
+
+For example, you can install other provider-specific packages like this:
```bash
$ yarn add @langchain/openai
@@ -66,11 +69,44 @@ leigh
```
Note that for compatibility, all used LangChain packages (including the base LangChain package, which itself depends on core!) must share the same version of `@langchain/core`.
-This means that you may need to install a specific version of `@langchain/core` that matches the dependencies of your used packages.
+This means that you may need to install/resolve a specific version of `@langchain/core` that matches the dependencies of your used packages.
+
+## 🔗 What is LangChain Expression Language?
+
+LangChain Core also contains LangChain Expression Language, or LCEL, a runtime that allows users to compose arbitrary sequences together and get several benefits that are important when building LLM applications.
+We call these sequences “runnables”.
+
+All runnables expose the same interface with single-invocation, batch, streaming and async methods.
+This design is useful because it is not enough to have a single sync interface when building an LLM application.
+Batch is needed for efficient processing of many inputs.
+Streaming (and streaming of intermediate steps) is needed to show the user that progress is being made.
+Async interfaces are nice when moving into production.
+Rather than having to write multiple implementations for all of those, LCEL allows you to write a runnable once and invoke it in many different ways.
+
+For more check out the [LCEL docs](https://js.langchain.com/docs/expression_language/).
+
+![LangChain Stack](../docs/core_docs/static/img/langchain_stack.png)
+
+## 📕 Releases & Versioning
+
+`@langchain/core` is currently on version `0.1.x`.
+
+As `@langchain/core` contains the base abstractions and runtime for the whole LangChain ecosystem, we will communicate any breaking changes with advance notice and version bumps. The exception for this is anything in `@langchain/core/beta`. The reason for `@langchain/core/beta` is that given the rate of change of the field, being able to move quickly is still a priority, and this module is our attempt to do so.
+
+Minor version increases will occur for:
+
+- Breaking changes for any public interfaces NOT in `@langchain/core/beta`
+
+Patch version increases will occur for:
+
+- Bug fixes
+- New features
+- Any changes to private interfaces
+- Any changes to `@langchain/core/beta`
## 📦 Creating your own package
-Other LangChain packages should add this package as a dependency and extend the classes within.
+Other LangChain packages should add this package as a dependency and extend the classes within.
For an example, see the [@langchain/anthropic](https://github.com/langchain-ai/langchainjs/tree/main/libs/langchain-anthropic) in this repo.
Because all used packages must share the same version of core, we suggest using a tilde dependency to allow for different (backwards-compatible) patch versions:
@@ -85,15 +121,13 @@ Because all used packages must share the same version of core, we suggest using
"license": "MIT",
"dependencies": {
"@anthropic-ai/sdk": "^0.10.0",
- "@langchain/core": "~0.0.1"
+ "@langchain/core": "~0.1.0"
}
}
```
This recommendation will change to a caret once a major version (1.x.x) release has occurred.
-API reference docs for core are in progress. For now we recommend looking directly at the source code to find the necessary abstractions for your use case.
-
We suggest making all packages cross-compatible with ESM and CJS using a build step like the one in
[@langchain/anthropic](https://github.com/langchain-ai/langchainjs/tree/main/libs/langchain-anthropic), then running `yarn build` before running `npm publish`.
diff --git a/langchain-core/package.json b/langchain-core/package.json
index 132e1840c301..2d05ad278c0d 100644
--- a/langchain-core/package.json
+++ b/langchain-core/package.json
@@ -1,6 +1,6 @@
{
"name": "@langchain/core",
- "version": "0.0.10",
+ "version": "0.1.1",
"description": "Core LangChain.js abstractions and schemas",
"type": "module",
"engines": {
@@ -13,8 +13,7 @@
"url": "git@github.com:langchain-ai/langchainjs.git"
},
"scripts": {
- "build": "yarn turbo run build:scripts",
- "build:envs": "yarn build:esm && yarn build:cjs",
+ "build": "yarn clean && yarn build:esm && yarn build:cjs && yarn run build:scripts",
"build:esm": "NODE_OPTIONS=--max-old-space-size=4096 tsc --outDir dist/ && rimraf dist/tests dist/**/tests",
"build:cjs": "NODE_OPTIONS=--max-old-space-size=4096 tsc --outDir dist-cjs/ -p tsconfig.cjs.json && node scripts/move-cjs-to-dist.js && rimraf dist-cjs",
"build:watch": "node scripts/create-entrypoints.js && tsc --outDir dist/ --watch",
@@ -40,6 +39,7 @@
"decamelize": "1.2.0",
"js-tiktoken": "^1.0.8",
"langsmith": "~0.0.48",
+ "ml-distance": "^4.0.0",
"p-queue": "^6.6.2",
"p-retry": "4",
"uuid": "^9.0.0",
@@ -59,6 +59,7 @@
"eslint-plugin-prettier": "^4.2.1",
"jest": "^29.5.0",
"jest-environment-node": "^29.6.4",
+ "ml-matrix": "^6.10.4",
"prettier": "^2.8.3",
"release-it": "^15.10.1",
"rimraf": "^5.0.1",
@@ -263,6 +264,11 @@
"import": "./utils/json_schema.js",
"require": "./utils/json_schema.cjs"
},
+ "./utils/math": {
+ "types": "./utils/math.d.ts",
+ "import": "./utils/math.js",
+ "require": "./utils/math.cjs"
+ },
"./utils/stream": {
"types": "./utils/stream.d.ts",
"import": "./utils/stream.js",
@@ -400,6 +406,9 @@
"utils/json_schema.cjs",
"utils/json_schema.js",
"utils/json_schema.d.ts",
+ "utils/math.cjs",
+ "utils/math.js",
+ "utils/math.d.ts",
"utils/stream.cjs",
"utils/stream.js",
"utils/stream.d.ts",
diff --git a/langchain-core/scripts/create-entrypoints.js b/langchain-core/scripts/create-entrypoints.js
index b49de2176afb..328796a52d64 100644
--- a/langchain-core/scripts/create-entrypoints.js
+++ b/langchain-core/scripts/create-entrypoints.js
@@ -44,6 +44,7 @@ const entrypoints = {
"utils/hash": "utils/hash",
"utils/json_patch": "utils/json_patch",
"utils/json_schema": "utils/json_schema",
+ "utils/math": "utils/math",
"utils/stream": "utils/stream",
"utils/testing": "utils/testing/index",
"utils/tiktoken": "utils/tiktoken",
diff --git a/langchain-core/src/documents/transformers.ts b/langchain-core/src/documents/transformers.ts
index b42ccab2dc16..45b5a6a06607 100644
--- a/langchain-core/src/documents/transformers.ts
+++ b/langchain-core/src/documents/transformers.ts
@@ -36,3 +36,20 @@ export abstract class BaseDocumentTransformer<
return this.transformDocuments(input);
}
}
+
+/**
+ * Class for document transformers that return exactly one transformed document
+ * for each input document.
+ */
+export abstract class MappingDocumentTransformer extends BaseDocumentTransformer {
+ async transformDocuments(documents: Document[]): Promise {
+ const newDocuments = [];
+ for (const document of documents) {
+ const transformedDocument = await this._transformDocument(document);
+ newDocuments.push(transformedDocument);
+ }
+ return newDocuments;
+ }
+
+ abstract _transformDocument(document: Document): Promise;
+}
diff --git a/langchain-core/src/load/import_map.ts b/langchain-core/src/load/import_map.ts
index 40fe9f8af9a4..0c94e2838e41 100644
--- a/langchain-core/src/load/import_map.ts
+++ b/langchain-core/src/load/import_map.ts
@@ -35,6 +35,7 @@ export * as utils__env from "../utils/env.js";
export * as utils__hash from "../utils/hash.js";
export * as utils__json_patch from "../utils/json_patch.js";
export * as utils__json_schema from "../utils/json_schema.js";
+export * as utils__math from "../utils/math.js";
export * as utils__stream from "../utils/stream.js";
export * as utils__testing from "../utils/testing/index.js";
export * as utils__tiktoken from "../utils/tiktoken.js";
diff --git a/langchain-core/src/load/index.ts b/langchain-core/src/load/index.ts
index 69e32bc52cbc..babdcd43ce08 100644
--- a/langchain-core/src/load/index.ts
+++ b/langchain-core/src/load/index.ts
@@ -6,7 +6,7 @@ import {
get_lc_unique_name,
} from "./serializable.js";
import { optionalImportEntrypoints as defaultOptionalImportEntrypoints } from "./import_constants.js";
-import * as defaultImportMap from "./import_map.js";
+import * as coreImportMap from "./import_map.js";
import type { OptionalImportMap, SecretMap } from "./import_type.js";
import { type SerializedFields, keyFromJson, mapKeys } from "./map_keys.js";
import { getEnvironmentVariable } from "../utils/env.js";
@@ -98,21 +98,32 @@ async function reviver(
const str = JSON.stringify(serialized);
const [name, ...namespaceReverse] = serialized.id.slice().reverse();
const namespace = namespaceReverse.reverse();
- const finalImportMap = { ...defaultImportMap, ...importMap };
+ const importMaps = { langchain_core: coreImportMap, langchain: importMap };
let module:
- | (typeof finalImportMap)[keyof typeof finalImportMap]
+ | (typeof importMaps)["langchain_core"][keyof (typeof importMaps)["langchain_core"]]
+ | (typeof importMaps)["langchain"][keyof (typeof importMaps)["langchain"]]
| OptionalImportMap[keyof OptionalImportMap]
| null = null;
+
+ const optionalImportNamespaceAliases = [namespace.join("/")];
+ if (namespace[0] === "langchain_community") {
+ optionalImportNamespaceAliases.push(
+ ["langchain", ...namespace.slice(1)].join("/")
+ );
+ }
+ const matchingNamespaceAlias = optionalImportNamespaceAliases.find(
+ (alias) => alias in optionalImportsMap
+ );
if (
defaultOptionalImportEntrypoints
.concat(optionalImportEntrypoints)
.includes(namespace.join("/")) ||
- namespace.join("/") in optionalImportsMap
+ matchingNamespaceAlias
) {
- if (namespace.join("/") in optionalImportsMap) {
+ if (matchingNamespaceAlias !== undefined) {
module = await optionalImportsMap[
- namespace.join("/") as keyof typeof optionalImportsMap
+ matchingNamespaceAlias as keyof typeof optionalImportsMap
];
} else {
throw new Error(
@@ -122,13 +133,12 @@ async function reviver(
);
}
} else {
- // Currently, we only support langchain imports.
- if (
- namespace[0] === "langchain" ||
- namespace[0] === "langchain_core" ||
- namespace[0] === "langchain_anthropic" ||
- namespace[0] === "langchain_openai"
- ) {
+ let finalImportMap:
+ | (typeof importMaps)["langchain"]
+ | (typeof importMaps)["langchain_core"];
+ // Currently, we only support langchain and langchain_core imports.
+ if (namespace[0] === "langchain" || namespace[0] === "langchain_core") {
+ finalImportMap = importMaps[namespace[0]];
namespace.shift();
} else {
throw new Error(`Invalid namespace: ${pathStr} -> ${str}`);
diff --git a/langchain-core/src/messages/index.ts b/langchain-core/src/messages/index.ts
index 9ddc2fd64e06..2019e67e7620 100644
--- a/langchain-core/src/messages/index.ts
+++ b/langchain-core/src/messages/index.ts
@@ -734,3 +734,29 @@ export function mapStoredMessageToChatMessage(message: StoredMessage) {
throw new Error(`Got unexpected type: ${storedMessage.type}`);
}
}
+
+/**
+ * Transforms an array of `StoredMessage` instances into an array of
+ * `BaseMessage` instances. It uses the `mapV1MessageToStoredMessage`
+ * function to ensure all messages are in the `StoredMessage` format, then
+ * creates new instances of the appropriate `BaseMessage` subclass based
+ * on the type of each message. This function is used to prepare stored
+ * messages for use in a chat context.
+ */
+export function mapStoredMessagesToChatMessages(
+ messages: StoredMessage[]
+): BaseMessage[] {
+ return messages.map(mapStoredMessageToChatMessage);
+}
+
+/**
+ * Transforms an array of `BaseMessage` instances into an array of
+ * `StoredMessage` instances. It does this by calling the `toDict` method
+ * on each `BaseMessage`, which returns a `StoredMessage`. This function
+ * is used to prepare chat messages for storage.
+ */
+export function mapChatMessagesToStoredMessages(
+ messages: BaseMessage[]
+): StoredMessage[] {
+ return messages.map((message) => message.toDict());
+}
diff --git a/langchain-core/src/runnables/base.ts b/langchain-core/src/runnables/base.ts
index 477ce73716c2..8504b24fdedd 100644
--- a/langchain-core/src/runnables/base.ts
+++ b/langchain-core/src/runnables/base.ts
@@ -31,11 +31,15 @@ export type RunnableFunc = (
| (Record & { config: RunnableConfig })
) => RunOutput | Promise;
+export type RunnableMapLike = {
+ [K in keyof RunOutput]: RunnableLike;
+};
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type RunnableLike =
| Runnable
| RunnableFunc
- | { [key: string]: RunnableLike };
+ | RunnableMapLike;
export type RunnableBatchOptions = {
maxConcurrency?: number;
@@ -1368,11 +1372,12 @@ export class RunnableSequence<
* const result = await mapChain.invoke({ topic: "bear" });
* ```
*/
-export class RunnableMap extends Runnable<
- RunInput,
+export class RunnableMap<
// eslint-disable-next-line @typescript-eslint/no-explicit-any
- Record
-> {
+ RunInput = any,
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ RunOutput extends Record = Record
+> extends Runnable {
static lc_name() {
return "RunnableMap";
}
@@ -1387,7 +1392,7 @@ export class RunnableMap extends Runnable<
return Object.keys(this.steps);
}
- constructor(fields: { steps: Record> }) {
+ constructor(fields: { steps: RunnableMapLike }) {
super(fields);
this.steps = {};
for (const [key, value] of Object.entries(fields.steps)) {
@@ -1395,15 +1400,20 @@ export class RunnableMap extends Runnable<
}
}
- static from(steps: Record>) {
- return new RunnableMap({ steps });
+ static from<
+ RunInput,
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ RunOutput extends Record = Record
+ >(
+ steps: RunnableMapLike
+ ): RunnableMap {
+ return new RunnableMap({ steps });
}
async invoke(
input: RunInput,
options?: Partial
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- ): Promise> {
+ ): Promise {
const callbackManager_ = await getCallbackMangerForConfig(options);
const runManager = await callbackManager_?.handleChainStart(
this.toJSON(),
@@ -1432,7 +1442,7 @@ export class RunnableMap extends Runnable<
throw e;
}
await runManager?.handleChainEnd(output);
- return output;
+ return output as RunOutput;
}
}
@@ -1487,6 +1497,8 @@ export class RunnableLambda extends Runnable<
}
}
+export class RunnableParallel extends RunnableMap {}
+
/**
* A Runnable that can fallback to other Runnables if it fails.
*/
@@ -1663,9 +1675,9 @@ export function _coerceToRunnable(
} else if (!Array.isArray(coerceable) && typeof coerceable === "object") {
const runnables: Record> = {};
for (const [key, value] of Object.entries(coerceable)) {
- runnables[key] = _coerceToRunnable(value);
+ runnables[key] = _coerceToRunnable(value as RunnableLike);
}
- return new RunnableMap({
+ return new RunnableMap({
steps: runnables,
}) as unknown as Runnable>;
} else {
diff --git a/langchain-core/src/runnables/index.ts b/langchain-core/src/runnables/index.ts
index 1409fb0d9580..dd8dce77c3e6 100644
--- a/langchain-core/src/runnables/index.ts
+++ b/langchain-core/src/runnables/index.ts
@@ -10,6 +10,7 @@ export {
RunnableRetry,
RunnableSequence,
RunnableMap,
+ RunnableParallel,
RunnableLambda,
RunnableWithFallbacks,
_coerceToRunnable,
diff --git a/langchain-core/src/runnables/tests/runnable.test.ts b/langchain-core/src/runnables/tests/runnable.test.ts
index 149a39112c4f..647df66282e2 100644
--- a/langchain-core/src/runnables/tests/runnable.test.ts
+++ b/langchain-core/src/runnables/tests/runnable.test.ts
@@ -10,21 +10,18 @@ import { StringOutputParser } from "../../output_parsers/string.js";
import {
ChatPromptTemplate,
SystemMessagePromptTemplate,
- HumanMessagePromptTemplate,
} from "../../prompts/chat.js";
import { PromptTemplate } from "../../prompts/prompt.js";
import {
FakeLLM,
FakeChatModel,
- FakeRetriever,
FakeStreamingLLM,
FakeSplitIntoListParser,
FakeRunnable,
FakeListChatModel,
} from "../../utils/testing/index.js";
-import { RunnableSequence, RunnableMap, RunnableLambda } from "../base.js";
+import { RunnableSequence, RunnableLambda } from "../base.js";
import { RouterRunnable } from "../router.js";
-import { Document } from "../../documents/document.js";
test("Test batch", async () => {
const llm = new FakeLLM({});
@@ -70,35 +67,6 @@ test("Pipe from one runnable to the next", async () => {
expect(result).toBe("Hello world!");
});
-test("Create a runnable sequence with a runnable map", async () => {
- const promptTemplate = ChatPromptTemplate.fromMessages<{
- documents: string;
- question: string;
- }>([
- SystemMessagePromptTemplate.fromTemplate(`You are a nice assistant.`),
- HumanMessagePromptTemplate.fromTemplate(
- `Context:\n{documents}\n\nQuestion:\n{question}`
- ),
- ]);
- const llm = new FakeChatModel({});
- const inputs = {
- question: (input: string) => input,
- documents: RunnableSequence.from([
- new FakeRetriever(),
- (docs: Document[]) => JSON.stringify(docs),
- ]),
- extraField: new FakeLLM({}),
- };
- const runnable = new RunnableMap({ steps: inputs })
- .pipe(promptTemplate)
- .pipe(llm);
- const result = await runnable.invoke("Do you know the Muffin Man?");
- console.log(result);
- expect(result.content).toEqual(
- `You are a nice assistant.\nContext:\n[{"pageContent":"foo","metadata":{}},{"pageContent":"bar","metadata":{}}]\n\nQuestion:\nDo you know the Muffin Man?`
- );
-});
-
test("Stream the entire way through", async () => {
const llm = new FakeStreamingLLM({});
const stream = await llm.pipe(new StringOutputParser()).stream("Hi there!");
diff --git a/langchain-core/src/runnables/tests/runnable_map.test.ts b/langchain-core/src/runnables/tests/runnable_map.test.ts
new file mode 100644
index 000000000000..d820e53ee0ed
--- /dev/null
+++ b/langchain-core/src/runnables/tests/runnable_map.test.ts
@@ -0,0 +1,105 @@
+/* eslint-disable no-promise-executor-return */
+/* eslint-disable @typescript-eslint/no-explicit-any */
+
+import { StringOutputParser } from "../../output_parsers/string.js";
+import {
+ ChatPromptTemplate,
+ SystemMessagePromptTemplate,
+ HumanMessagePromptTemplate,
+} from "../../prompts/chat.js";
+import {
+ FakeLLM,
+ FakeChatModel,
+ FakeRetriever,
+} from "../../utils/testing/index.js";
+import { RunnableSequence, RunnableMap } from "../base.js";
+import { RunnablePassthrough } from "../passthrough.js";
+
+test("Create a runnable sequence with a runnable map", async () => {
+ const promptTemplate = ChatPromptTemplate.fromMessages<{
+ documents: string;
+ question: string;
+ }>([
+ SystemMessagePromptTemplate.fromTemplate(`You are a nice assistant.`),
+ HumanMessagePromptTemplate.fromTemplate(
+ `Context:\n{documents}\n\nQuestion:\n{question}`
+ ),
+ ]);
+ const llm = new FakeChatModel({});
+ const inputs = {
+ question: (input: string) => input,
+ documents: RunnableSequence.from([
+ new FakeRetriever(),
+ (docs: Document[]) => JSON.stringify(docs),
+ ]),
+ extraField: new FakeLLM({}),
+ };
+ const runnable = new RunnableMap({ steps: inputs })
+ .pipe(promptTemplate)
+ .pipe(llm);
+ const result = await runnable.invoke("Do you know the Muffin Man?");
+ console.log(result);
+ expect(result.content).toEqual(
+ `You are a nice assistant.\nContext:\n[{"pageContent":"foo","metadata":{}},{"pageContent":"bar","metadata":{}}]\n\nQuestion:\nDo you know the Muffin Man?`
+ );
+});
+
+test("Test map inference in a sequence", async () => {
+ const prompt = ChatPromptTemplate.fromTemplate(
+ "context: {context}, question: {question}"
+ );
+ const chain = RunnableSequence.from([
+ {
+ question: new RunnablePassthrough(),
+ context: async () => "SOME STUFF",
+ },
+ prompt,
+ new FakeLLM({}),
+ new StringOutputParser(),
+ ]);
+ const response = await chain.invoke("Just passing through.");
+ console.log(response);
+ expect(response).toBe(
+ `Human: context: SOME STUFF, question: Just passing through.`
+ );
+});
+
+test("Should not allow mismatched inputs", async () => {
+ const prompt = ChatPromptTemplate.fromTemplate(
+ "context: {context}, question: {question}"
+ );
+ const badChain = RunnableSequence.from([
+ {
+ // @ts-expect-error TS compiler should flag mismatched input types
+ question: new FakeLLM({}),
+ context: async (input: number) => input,
+ },
+ prompt,
+ new FakeLLM({}),
+ new StringOutputParser(),
+ ]);
+ console.log(badChain);
+});
+
+test("Should not allow improper inputs into a map in a sequence", async () => {
+ const prompt = ChatPromptTemplate.fromTemplate(
+ "context: {context}, question: {question}"
+ );
+ const map = RunnableMap.from({
+ question: new FakeLLM({}),
+ context: async (_input: string) => 9,
+ });
+ // @ts-expect-error TS compiler should flag mismatched output types
+ const runnable = prompt.pipe(map);
+ console.log(runnable);
+});
+
+test("Should not allow improper outputs from a map into the next item in a sequence", async () => {
+ const map = RunnableMap.from({
+ question: new FakeLLM({}),
+ context: async (_input: string) => 9,
+ });
+ // @ts-expect-error TS compiler should flag mismatched output types
+ const runnable = map.pipe(new FakeLLM({}));
+ console.log(runnable);
+});
diff --git a/langchain-core/src/runnables/tests/runnable_stream_log.test.ts b/langchain-core/src/runnables/tests/runnable_stream_log.test.ts
index 8f7c1d1e589a..f9ab046be648 100644
--- a/langchain-core/src/runnables/tests/runnable_stream_log.test.ts
+++ b/langchain-core/src/runnables/tests/runnable_stream_log.test.ts
@@ -62,7 +62,10 @@ test("Runnable streamLog method with a more complicated sequence", async () => {
response: "testing",
}).withConfig({ tags: ["only_one"] }),
};
- const runnable = new RunnableMap({ steps: inputs })
+
+ const runnable = new RunnableMap({
+ steps: inputs,
+ })
.pipe(promptTemplate)
.pipe(llm);
const stream = await runnable.streamLog(
diff --git a/langchain-core/src/tools.ts b/langchain-core/src/tools.ts
index eeedab18ecd8..84b5311eac39 100644
--- a/langchain-core/src/tools.ts
+++ b/langchain-core/src/tools.ts
@@ -150,7 +150,7 @@ export abstract class Tool extends StructuredTool {
*/
call(
arg: string | undefined | z.input,
- callbacks?: Callbacks
+ callbacks?: Callbacks | RunnableConfig
): Promise {
return super.call(
typeof arg === "string" || !arg ? { input: arg } : arg,
diff --git a/langchain-core/src/utils/math.ts b/langchain-core/src/utils/math.ts
new file mode 100644
index 000000000000..fe703c2d5f79
--- /dev/null
+++ b/langchain-core/src/utils/math.ts
@@ -0,0 +1,180 @@
+import {
+ similarity as ml_distance_similarity,
+ distance as ml_distance,
+} from "ml-distance";
+
+type VectorFunction = (xVector: number[], yVector: number[]) => number;
+
+/**
+ * Apply a row-wise function between two matrices with the same number of columns.
+ *
+ * @param {number[][]} X - The first matrix.
+ * @param {number[][]} Y - The second matrix.
+ * @param {VectorFunction} func - The function to apply.
+ *
+ * @throws {Error} If the number of columns in X and Y are not the same.
+ *
+ * @returns {number[][] | [[]]} A matrix where each row represents the result of applying the function between the corresponding rows of X and Y.
+ */
+
+export function matrixFunc(
+ X: number[][],
+ Y: number[][],
+ func: VectorFunction
+): number[][] {
+ if (
+ X.length === 0 ||
+ X[0].length === 0 ||
+ Y.length === 0 ||
+ Y[0].length === 0
+ ) {
+ return [[]];
+ }
+
+ if (X[0].length !== Y[0].length) {
+ throw new Error(
+ `Number of columns in X and Y must be the same. X has shape ${[
+ X.length,
+ X[0].length,
+ ]} and Y has shape ${[Y.length, Y[0].length]}.`
+ );
+ }
+
+ return X.map((xVector) =>
+ Y.map((yVector) => func(xVector, yVector)).map((similarity) =>
+ Number.isNaN(similarity) ? 0 : similarity
+ )
+ );
+}
+
+export function normalize(M: number[][], similarity = false): number[][] {
+ const max = matrixMaxVal(M);
+ return M.map((row) =>
+ row.map((val) => (similarity ? 1 - val / max : val / max))
+ );
+}
+
+/**
+ * This function calculates the row-wise cosine similarity between two matrices with the same number of columns.
+ *
+ * @param {number[][]} X - The first matrix.
+ * @param {number[][]} Y - The second matrix.
+ *
+ * @throws {Error} If the number of columns in X and Y are not the same.
+ *
+ * @returns {number[][] | [[]]} A matrix where each row represents the cosine similarity values between the corresponding rows of X and Y.
+ */
+export function cosineSimilarity(X: number[][], Y: number[][]): number[][] {
+ return matrixFunc(X, Y, ml_distance_similarity.cosine);
+}
+
+export function innerProduct(X: number[][], Y: number[][]): number[][] {
+ return matrixFunc(X, Y, ml_distance.innerProduct);
+}
+
+export function euclideanDistance(X: number[][], Y: number[][]): number[][] {
+ return matrixFunc(X, Y, ml_distance.euclidean);
+}
+
+/**
+ * This function implements the Maximal Marginal Relevance algorithm
+ * to select a set of embeddings that maximizes the diversity and relevance to a query embedding.
+ *
+ * @param {number[]|number[][]} queryEmbedding - The query embedding.
+ * @param {number[][]} embeddingList - The list of embeddings to select from.
+ * @param {number} [lambda=0.5] - The trade-off parameter between relevance and diversity.
+ * @param {number} [k=4] - The maximum number of embeddings to select.
+ *
+ * @returns {number[]} The indexes of the selected embeddings in the embeddingList.
+ */
+export function maximalMarginalRelevance(
+ queryEmbedding: number[] | number[][],
+ embeddingList: number[][],
+ lambda = 0.5,
+ k = 4
+): number[] {
+ if (Math.min(k, embeddingList.length) <= 0) {
+ return [];
+ }
+
+ const queryEmbeddingExpanded = (
+ Array.isArray(queryEmbedding[0]) ? queryEmbedding : [queryEmbedding]
+ ) as number[][];
+
+ const similarityToQuery = cosineSimilarity(
+ queryEmbeddingExpanded,
+ embeddingList
+ )[0];
+ const mostSimilarEmbeddingIndex = argMax(similarityToQuery).maxIndex;
+
+ const selectedEmbeddings = [embeddingList[mostSimilarEmbeddingIndex]];
+ const selectedEmbeddingsIndexes = [mostSimilarEmbeddingIndex];
+
+ while (selectedEmbeddingsIndexes.length < Math.min(k, embeddingList.length)) {
+ let bestScore = -Infinity;
+ let bestIndex = -1;
+
+ const similarityToSelected = cosineSimilarity(
+ embeddingList,
+ selectedEmbeddings
+ );
+
+ similarityToQuery.forEach((queryScore, queryScoreIndex) => {
+ if (selectedEmbeddingsIndexes.includes(queryScoreIndex)) {
+ return;
+ }
+ const maxSimilarityToSelected = Math.max(
+ ...similarityToSelected[queryScoreIndex]
+ );
+ const score =
+ lambda * queryScore - (1 - lambda) * maxSimilarityToSelected;
+
+ if (score > bestScore) {
+ bestScore = score;
+ bestIndex = queryScoreIndex;
+ }
+ });
+ selectedEmbeddings.push(embeddingList[bestIndex]);
+ selectedEmbeddingsIndexes.push(bestIndex);
+ }
+
+ return selectedEmbeddingsIndexes;
+}
+
+type MaxInfo = {
+ maxIndex: number;
+ maxValue: number;
+};
+
+/**
+ * Finds the index of the maximum value in the given array.
+ * @param {number[]} array - The input array.
+ *
+ * @returns {number} The index of the maximum value in the array. If the array is empty, returns -1.
+ */
+function argMax(array: number[]): MaxInfo {
+ if (array.length === 0) {
+ return {
+ maxIndex: -1,
+ maxValue: NaN,
+ };
+ }
+
+ let maxValue = array[0];
+ let maxIndex = 0;
+
+ for (let i = 1; i < array.length; i += 1) {
+ if (array[i] > maxValue) {
+ maxIndex = i;
+ maxValue = array[i];
+ }
+ }
+ return { maxIndex, maxValue };
+}
+
+function matrixMaxVal(arrays: number[][]): number {
+ return arrays.reduce(
+ (acc, array) => Math.max(acc, argMax(array).maxValue),
+ 0
+ );
+}
diff --git a/langchain/src/util/tests/math_utils.test.ts b/langchain-core/src/utils/tests/math_utils.test.ts
similarity index 100%
rename from langchain/src/util/tests/math_utils.test.ts
rename to langchain-core/src/utils/tests/math_utils.test.ts
diff --git a/langchain-core/turbo.json b/langchain-core/turbo.json
deleted file mode 100644
index 5fe0abbb4ad8..000000000000
--- a/langchain-core/turbo.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
- "$schema": "https://turbo.build/schema.json",
- "extends": ["//"],
- "pipeline": {
- "build:scripts": {
- "outputs": [
- "tsconfig.json",
- "package.json",
- "**/*.js",
- "**/*.d.ts",
- "**/*.cjs",
- "dist-cjs/**"
- ],
- "dependsOn": ["build:envs"]
- },
- "build:envs": {
- "dependsOn": ["clean"]
- },
- "clean": {
- "outputs": [".turbo/**", "dist/**"]
- }
- }
-}
diff --git a/langchain/package.json b/langchain/package.json
index 5c1b3fe2ce79..f3eabd2e448d 100644
--- a/langchain/package.json
+++ b/langchain/package.json
@@ -1,6 +1,6 @@
{
"name": "langchain",
- "version": "0.0.203",
+ "version": "0.0.206",
"description": "Typescript bindings for langchain",
"type": "module",
"engines": {
@@ -859,7 +859,8 @@
"url": "git@github.com:langchain-ai/langchainjs.git"
},
"scripts": {
- "build": "yarn clean && yarn build:esm && yarn build:cjs && yarn build:scripts",
+ "build": "yarn run build:deps && yarn clean && yarn build:esm && yarn build:cjs && yarn build:scripts",
+ "build:deps": "yarn run turbo:command build --filter=@langchain/core --filter=@langchain/anthropic --filter=@langchain/openai --filter=@langchain/community --concurrency=1",
"build:esm": "NODE_OPTIONS=--max-old-space-size=4096 tsc --outDir dist/ && rimraf dist/tests dist/**/tests",
"build:cjs": "NODE_OPTIONS=--max-old-space-size=4096 tsc --outDir dist-cjs/ -p tsconfig.cjs.json && node scripts/move-cjs-to-dist.js && rimraf dist-cjs",
"build:watch": "node scripts/create-entrypoints.js && tsc --outDir dist/ --watch",
@@ -872,94 +873,52 @@
"clean": "rimraf .turbo/ dist/ && NODE_OPTIONS=--max-old-space-size=4096 node scripts/create-entrypoints.js pre",
"prepack": "yarn build",
"release": "release-it --only-version --config .release-it.json",
- "test": "NODE_OPTIONS=--experimental-vm-modules jest --testPathIgnorePatterns=\\.int\\.test.ts --testTimeout 30000 --maxWorkers=50%",
- "test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch --testPathIgnorePatterns=\\.int\\.test.ts",
- "test:integration": "NODE_OPTIONS=--experimental-vm-modules jest --testPathPattern=\\.int\\.test.ts --testTimeout 100000 --maxWorkers=50%",
- "test:single": "NODE_OPTIONS=--experimental-vm-modules yarn run jest --config jest.config.cjs --testTimeout 100000",
+ "test": "yarn run build:deps && NODE_OPTIONS=--experimental-vm-modules jest --testPathIgnorePatterns=\\.int\\.test.ts --testTimeout 30000 --maxWorkers=50%",
+ "test:watch": "yarn run build:deps && NODE_OPTIONS=--experimental-vm-modules jest --watch --testPathIgnorePatterns=\\.int\\.test.ts",
+ "test:integration": "yarn run build:deps && NODE_OPTIONS=--experimental-vm-modules jest --testPathPattern=\\.int\\.test.ts --testTimeout 100000 --maxWorkers=50%",
+ "test:single": "yarn run build:deps && NODE_OPTIONS=--experimental-vm-modules yarn run jest --config jest.config.cjs --testTimeout 100000",
"format": "prettier --write \"src\"",
"format:check": "prettier --check \"src\""
},
"author": "LangChain",
"license": "MIT",
"devDependencies": {
- "@aws-crypto/sha256-js": "^5.0.0",
- "@aws-sdk/client-bedrock-runtime": "^3.422.0",
- "@aws-sdk/client-dynamodb": "^3.310.0",
- "@aws-sdk/client-kendra": "^3.352.0",
- "@aws-sdk/client-lambda": "^3.310.0",
"@aws-sdk/client-s3": "^3.310.0",
"@aws-sdk/client-sagemaker-runtime": "^3.414.0",
"@aws-sdk/client-sfn": "^3.362.0",
"@aws-sdk/credential-provider-node": "^3.388.0",
"@aws-sdk/types": "^3.357.0",
"@azure/storage-blob": "^12.15.0",
- "@clickhouse/client": "^0.2.5",
- "@cloudflare/ai": "^1.0.12",
"@cloudflare/workers-types": "^4.20230922.0",
- "@elastic/elasticsearch": "^8.4.0",
"@faker-js/faker": "^7.6.0",
- "@getmetal/metal-sdk": "^4.0.0",
- "@getzep/zep-js": "^0.9.0",
"@gomomento/sdk": "^1.51.1",
"@gomomento/sdk-core": "^1.51.1",
"@google-ai/generativelanguage": "^0.2.1",
"@google-cloud/storage": "^6.10.1",
- "@gradientai/nodejs-sdk": "^1.2.0",
- "@huggingface/inference": "^2.6.4",
"@jest/globals": "^29.5.0",
- "@mozilla/readability": "^0.4.4",
"@notionhq/client": "^2.2.10",
- "@opensearch-project/opensearch": "^2.2.0",
"@pinecone-database/pinecone": "^1.1.0",
- "@planetscale/database": "^1.8.0",
- "@qdrant/js-client-rest": "^1.2.0",
- "@raycast/api": "^1.55.2",
- "@rockset/client": "^0.9.1",
- "@smithy/eventstream-codec": "^2.0.5",
- "@smithy/protocol-http": "^3.0.6",
- "@smithy/signature-v4": "^2.0.10",
- "@smithy/util-utf8": "^2.0.0",
- "@supabase/postgrest-js": "^1.1.1",
"@supabase/supabase-js": "^2.10.0",
"@swc/core": "^1.3.90",
"@swc/jest": "^0.2.29",
- "@tensorflow-models/universal-sentence-encoder": "^1.3.3",
- "@tensorflow/tfjs-backend-cpu": "^3",
- "@tensorflow/tfjs-converter": "^3.6.0",
- "@tensorflow/tfjs-core": "^3.6.0",
"@tsconfig/recommended": "^1.0.2",
"@types/d3-dsv": "^2",
"@types/decamelize": "^1.2.0",
- "@types/flat": "^5.0.2",
"@types/html-to-text": "^9",
"@types/js-yaml": "^4",
"@types/jsdom": "^21.1.1",
- "@types/lodash": "^4",
- "@types/mozilla-readability": "^0.2.1",
"@types/pdf-parse": "^1.1.1",
- "@types/pg": "^8",
- "@types/pg-copy-streams": "^1.2.2",
"@types/uuid": "^9",
"@types/ws": "^8",
"@typescript-eslint/eslint-plugin": "^5.58.0",
"@typescript-eslint/parser": "^5.58.0",
- "@upstash/redis": "^1.20.6",
"@vercel/kv": "^0.2.3",
- "@vercel/postgres": "^0.5.0",
- "@writerai/writer-sdk": "^0.40.2",
"@xata.io/client": "^0.28.0",
- "@xenova/transformers": "^2.5.4",
- "@zilliz/milvus2-sdk-node": ">=2.2.11",
"apify-client": "^2.7.1",
"assemblyai": "^2.0.2",
"axios": "^0.26.0",
- "cassandra-driver": "^4.7.2",
"cheerio": "^1.0.0-rc.12",
"chromadb": "^1.5.3",
- "closevector-common": "0.1.0-alpha.1",
- "closevector-node": "0.1.0-alpha.10",
- "closevector-web": "0.1.0-alpha.15",
- "cohere-ai": ">=6.0.0",
"convex": "^1.3.1",
"d3-dsv": "^2.0.0",
"dotenv": "^16.0.3",
@@ -972,156 +931,87 @@
"eslint-plugin-jest": "^27.6.0",
"eslint-plugin-no-instanceof": "^1.0.1",
"eslint-plugin-prettier": "^4.2.1",
- "faiss-node": "^0.5.1",
"fast-xml-parser": "^4.2.7",
- "firebase-admin": "^11.9.0",
"google-auth-library": "^8.9.0",
"googleapis": "^126.0.1",
- "graphql": "^16.6.0",
- "hnswlib-node": "^1.4.2",
"html-to-text": "^9.0.5",
"ignore": "^5.2.0",
"ioredis": "^5.3.2",
"jest": "^29.5.0",
"jest-environment-node": "^29.6.4",
"jsdom": "^22.1.0",
- "llmonitor": "^0.5.9",
- "lodash": "^4.17.21",
"mammoth": "^1.5.1",
- "ml-matrix": "^6.10.4",
"mongodb": "^5.2.0",
- "mysql2": "^3.3.3",
- "neo4j-driver": "^5.12.0",
"node-llama-cpp": "2.7.3",
"notion-to-md": "^3.1.0",
"officeparser": "^4.0.4",
"pdf-parse": "1.1.1",
"peggy": "^3.0.2",
- "pg": "^8.11.0",
- "pg-copy-streams": "^6.0.5",
- "pickleparser": "^0.2.1",
"playwright": "^1.32.1",
- "portkey-ai": "^0.1.11",
"prettier": "^2.8.3",
"puppeteer": "^19.7.2",
"pyodide": "^0.24.1",
"redis": "^4.6.6",
"release-it": "^15.10.1",
- "replicate": "^0.18.0",
"rimraf": "^5.0.1",
"rollup": "^3.19.1",
"sonix-speech-recognition": "^2.1.1",
- "sqlite3": "^5.1.4",
"srt-parser-2": "^1.2.2",
"ts-jest": "^29.1.0",
"typeorm": "^0.3.12",
"typescript": "~5.1.6",
- "typesense": "^1.5.3",
- "usearch": "^1.1.1",
"vectordb": "^0.1.4",
- "voy-search": "0.6.2",
"weaviate-ts-client": "^1.4.0",
"web-auth-library": "^1.0.3",
"youtube-transcript": "^1.0.6",
"youtubei.js": "^5.8.0"
},
"peerDependencies": {
- "@aws-crypto/sha256-js": "^5.0.0",
- "@aws-sdk/client-bedrock-runtime": "^3.422.0",
- "@aws-sdk/client-dynamodb": "^3.310.0",
- "@aws-sdk/client-kendra": "^3.352.0",
- "@aws-sdk/client-lambda": "^3.310.0",
"@aws-sdk/client-s3": "^3.310.0",
"@aws-sdk/client-sagemaker-runtime": "^3.310.0",
"@aws-sdk/client-sfn": "^3.310.0",
"@aws-sdk/credential-provider-node": "^3.388.0",
"@azure/storage-blob": "^12.15.0",
- "@clickhouse/client": "^0.2.5",
- "@cloudflare/ai": "^1.0.12",
- "@elastic/elasticsearch": "^8.4.0",
- "@getmetal/metal-sdk": "*",
- "@getzep/zep-js": "^0.9.0",
"@gomomento/sdk": "^1.51.1",
"@gomomento/sdk-core": "^1.51.1",
"@gomomento/sdk-web": "^1.51.1",
"@google-ai/generativelanguage": "^0.2.1",
"@google-cloud/storage": "^6.10.1",
- "@gradientai/nodejs-sdk": "^1.2.0",
- "@huggingface/inference": "^2.6.4",
- "@mozilla/readability": "*",
"@notionhq/client": "^2.2.10",
- "@opensearch-project/opensearch": "*",
"@pinecone-database/pinecone": "^1.1.0",
- "@planetscale/database": "^1.8.0",
- "@qdrant/js-client-rest": "^1.2.0",
- "@raycast/api": "^1.55.2",
- "@rockset/client": "^0.9.1",
- "@smithy/eventstream-codec": "^2.0.5",
- "@smithy/protocol-http": "^3.0.6",
- "@smithy/signature-v4": "^2.0.10",
- "@smithy/util-utf8": "^2.0.0",
- "@supabase/postgrest-js": "^1.1.1",
"@supabase/supabase-js": "^2.10.0",
- "@tensorflow-models/universal-sentence-encoder": "*",
- "@tensorflow/tfjs-converter": "*",
- "@tensorflow/tfjs-core": "*",
- "@upstash/redis": "^1.20.6",
"@vercel/kv": "^0.2.3",
- "@vercel/postgres": "^0.5.0",
- "@writerai/writer-sdk": "^0.40.2",
"@xata.io/client": "^0.28.0",
- "@xenova/transformers": "^2.5.4",
- "@zilliz/milvus2-sdk-node": ">=2.2.7",
"apify-client": "^2.7.1",
"assemblyai": "^2.0.2",
"axios": "*",
- "cassandra-driver": "^4.7.2",
"cheerio": "^1.0.0-rc.12",
"chromadb": "*",
- "closevector-common": "0.1.0-alpha.1",
- "closevector-node": "0.1.0-alpha.10",
- "closevector-web": "0.1.0-alpha.16",
- "cohere-ai": ">=6.0.0",
"convex": "^1.3.1",
"d3-dsv": "^2.0.0",
"epub2": "^3.0.1",
- "faiss-node": "^0.5.1",
"fast-xml-parser": "^4.2.7",
- "firebase-admin": "^11.9.0",
"google-auth-library": "^8.9.0",
"googleapis": "^126.0.1",
- "hnswlib-node": "^1.4.2",
"html-to-text": "^9.0.5",
"ignore": "^5.2.0",
"ioredis": "^5.3.2",
"jsdom": "*",
- "llmonitor": "^0.5.9",
- "lodash": "^4.17.21",
"mammoth": "*",
"mongodb": "^5.2.0",
- "mysql2": "^3.3.3",
- "neo4j-driver": "*",
"node-llama-cpp": "*",
"notion-to-md": "^3.1.0",
"officeparser": "^4.0.4",
"pdf-parse": "1.1.1",
"peggy": "^3.0.2",
- "pg": "^8.11.0",
- "pg-copy-streams": "^6.0.5",
- "pickleparser": "^0.2.1",
"playwright": "^1.32.1",
- "portkey-ai": "^0.1.11",
"puppeteer": "^19.7.2",
"pyodide": "^0.24.1",
"redis": "^4.6.4",
- "replicate": "^0.18.0",
"sonix-speech-recognition": "^2.1.1",
"srt-parser-2": "^1.2.2",
"typeorm": "^0.3.12",
- "typesense": "^1.5.3",
- "usearch": "^1.1.1",
"vectordb": "^0.1.4",
- "voy-search": "0.6.2",
"weaviate-ts-client": "^1.4.0",
"web-auth-library": "^1.0.3",
"ws": "^8.14.2",
@@ -1129,21 +1019,6 @@
"youtubei.js": "^5.8.0"
},
"peerDependenciesMeta": {
- "@aws-crypto/sha256-js": {
- "optional": true
- },
- "@aws-sdk/client-bedrock-runtime": {
- "optional": true
- },
- "@aws-sdk/client-dynamodb": {
- "optional": true
- },
- "@aws-sdk/client-kendra": {
- "optional": true
- },
- "@aws-sdk/client-lambda": {
- "optional": true
- },
"@aws-sdk/client-s3": {
"optional": true
},
@@ -1159,21 +1034,6 @@
"@azure/storage-blob": {
"optional": true
},
- "@clickhouse/client": {
- "optional": true
- },
- "@cloudflare/ai": {
- "optional": true
- },
- "@elastic/elasticsearch": {
- "optional": true
- },
- "@getmetal/metal-sdk": {
- "optional": true
- },
- "@getzep/zep-js": {
- "optional": true
- },
"@gomomento/sdk": {
"optional": true
},
@@ -1189,84 +1049,21 @@
"@google-cloud/storage": {
"optional": true
},
- "@gradientai/nodejs-sdk": {
- "optional": true
- },
- "@huggingface/inference": {
- "optional": true
- },
- "@mozilla/readability": {
- "optional": true
- },
"@notionhq/client": {
"optional": true
},
- "@opensearch-project/opensearch": {
- "optional": true
- },
"@pinecone-database/pinecone": {
"optional": true
},
- "@planetscale/database": {
- "optional": true
- },
- "@qdrant/js-client-rest": {
- "optional": true
- },
- "@raycast/api": {
- "optional": true
- },
- "@rockset/client": {
- "optional": true
- },
- "@smithy/eventstream-codec": {
- "optional": true
- },
- "@smithy/protocol-http": {
- "optional": true
- },
- "@smithy/signature-v4": {
- "optional": true
- },
- "@smithy/util-utf8": {
- "optional": true
- },
- "@supabase/postgrest-js": {
- "optional": true
- },
"@supabase/supabase-js": {
"optional": true
},
- "@tensorflow-models/universal-sentence-encoder": {
- "optional": true
- },
- "@tensorflow/tfjs-converter": {
- "optional": true
- },
- "@tensorflow/tfjs-core": {
- "optional": true
- },
- "@upstash/redis": {
- "optional": true
- },
"@vercel/kv": {
"optional": true
},
- "@vercel/postgres": {
- "optional": true
- },
- "@writerai/writer-sdk": {
- "optional": true
- },
"@xata.io/client": {
"optional": true
},
- "@xenova/transformers": {
- "optional": true
- },
- "@zilliz/milvus2-sdk-node": {
- "optional": true
- },
"apify-client": {
"optional": true
},
@@ -1276,27 +1073,12 @@
"axios": {
"optional": true
},
- "cassandra-driver": {
- "optional": true
- },
"cheerio": {
"optional": true
},
"chromadb": {
"optional": true
},
- "closevector-common": {
- "optional": true
- },
- "closevector-node": {
- "optional": true
- },
- "closevector-web": {
- "optional": true
- },
- "cohere-ai": {
- "optional": true
- },
"convex": {
"optional": true
},
@@ -1312,18 +1094,12 @@
"fast-xml-parser": {
"optional": true
},
- "firebase-admin": {
- "optional": true
- },
"google-auth-library": {
"optional": true
},
"googleapis": {
"optional": true
},
- "hnswlib-node": {
- "optional": true
- },
"html-to-text": {
"optional": true
},
@@ -1336,24 +1112,12 @@
"jsdom": {
"optional": true
},
- "llmonitor": {
- "optional": true
- },
- "lodash": {
- "optional": true
- },
"mammoth": {
"optional": true
},
"mongodb": {
"optional": true
},
- "mysql2": {
- "optional": true
- },
- "neo4j-driver": {
- "optional": true
- },
"node-llama-cpp": {
"optional": true
},
@@ -1369,21 +1133,9 @@
"peggy": {
"optional": true
},
- "pg": {
- "optional": true
- },
- "pg-copy-streams": {
- "optional": true
- },
- "pickleparser": {
- "optional": true
- },
"playwright": {
"optional": true
},
- "portkey-ai": {
- "optional": true
- },
"puppeteer": {
"optional": true
},
@@ -1393,9 +1145,6 @@
"redis": {
"optional": true
},
- "replicate": {
- "optional": true
- },
"sonix-speech-recognition": {
"optional": true
},
@@ -1405,18 +1154,9 @@
"typeorm": {
"optional": true
},
- "typesense": {
- "optional": true
- },
- "usearch": {
- "optional": true
- },
"vectordb": {
"optional": true
},
- "voy-search": {
- "optional": true
- },
"weaviate-ts-client": {
"optional": true
},
@@ -1435,17 +1175,17 @@
},
"dependencies": {
"@anthropic-ai/sdk": "^0.9.1",
- "@langchain/core": "~0.0.10",
+ "@langchain/community": "~0.0.4",
+ "@langchain/core": "~0.1.1",
+ "@langchain/openai": "~0.0.5",
"binary-extensions": "^2.2.0",
"expr-eval": "^2.0.2",
- "flat": "^5.0.2",
"js-tiktoken": "^1.0.7",
"js-yaml": "^4.1.0",
"jsonpointer": "^5.0.1",
"langchainhub": "~0.0.6",
"langsmith": "~0.0.48",
"ml-distance": "^4.0.0",
- "openai": "^4.19.0",
"openapi-types": "^12.1.3",
"p-retry": "4",
"uuid": "^9.0.0",
diff --git a/langchain/scripts/check-tree-shaking.js b/langchain/scripts/check-tree-shaking.js
index 66a1f194199f..bae5213269d7 100644
--- a/langchain/scripts/check-tree-shaking.js
+++ b/langchain/scripts/check-tree-shaking.js
@@ -28,6 +28,7 @@ export function listExternals() {
/node\:/,
/js-tiktoken/,
/@langchain\/core/,
+ /@langchain\/community/,
"axios", // axios is a dependency of openai
"convex",
"convex/server",
diff --git a/langchain/scripts/create-entrypoints.js b/langchain/scripts/create-entrypoints.js
index e5bb0b7c3b2e..cf592165b424 100644
--- a/langchain/scripts/create-entrypoints.js
+++ b/langchain/scripts/create-entrypoints.js
@@ -578,7 +578,7 @@ const updateConfig = () => {
...json,
entryPoints: [...Object.keys(entrypoints)]
.filter((key) => !deprecatedNodeOnly.includes(key))
- .map((key) => `./langchain/src/${entrypoints[key]}.ts`),
+ .map((key) => `../../langchain/src/${entrypoints[key]}.ts`),
}));
const generatedFiles = generateFiles();
diff --git a/langchain/src/agents/openai/output_parser.ts b/langchain/src/agents/openai/output_parser.ts
index 960f6db84e47..fc14b6a4f160 100644
--- a/langchain/src/agents/openai/output_parser.ts
+++ b/langchain/src/agents/openai/output_parser.ts
@@ -1,4 +1,4 @@
-import type { OpenAI as OpenAIClient } from "openai";
+import type { OpenAIClient } from "@langchain/openai";
import {
AgentAction,
AgentFinish,
diff --git a/langchain/src/agents/toolkits/aws_sfn.ts b/langchain/src/agents/toolkits/aws_sfn.ts
index 810db0eed1a9..b0438dd37624 100644
--- a/langchain/src/agents/toolkits/aws_sfn.ts
+++ b/langchain/src/agents/toolkits/aws_sfn.ts
@@ -1,17 +1,15 @@
-import { Tool } from "../../tools/base.js";
import {
- SfnConfig,
- StartExecutionAWSSfnTool,
- DescribeExecutionAWSSfnTool,
- SendTaskSuccessAWSSfnTool,
-} from "../../tools/aws_sfn.js";
-import { Toolkit } from "./base.js";
+ type AWSSfnToolkitArgs,
+ AWSSfnToolkit,
+} from "@langchain/community/agents/toolkits/aws_sfn";
import { BaseLanguageModel } from "../../base_language/index.js";
import { renderTemplate } from "../../prompts/template.js";
import { LLMChain } from "../../chains/llm_chain.js";
import { ZeroShotAgent, ZeroShotCreatePromptArgs } from "../mrkl/index.js";
import { AgentExecutor } from "../executor.js";
+export { AWSSfnToolkit, type AWSSfnToolkitArgs };
+
export const SFN_PREFIX = `You are an agent designed to interact with AWS Step Functions state machines to execute and coordinate asynchronous workflows and tasks.
Given an input question, command, or task use the appropriate tool to execute a command to interact with AWS Step Functions and return the result.
You have access to tools for interacting with AWS Step Functions.
@@ -28,91 +26,6 @@ Thought: I should look at state machines within AWS Step Functions to see what a
export interface AWSSfnCreatePromptArgs extends ZeroShotCreatePromptArgs {}
-/**
- * Interface for the arguments required to create an AWS Step Functions
- * toolkit.
- */
-export interface AWSSfnToolkitArgs {
- name: string;
- description: string;
- stateMachineArn: string;
- asl?: string;
- llm?: BaseLanguageModel;
-}
-
-/**
- * Class representing a toolkit for interacting with AWS Step Functions.
- * It initializes the AWS Step Functions tools and provides them as tools
- * for the agent.
- * @example
- * ```typescript
- *
- * const toolkit = new AWSSfnToolkit({
- * name: "onboard-new-client-workflow",
- * description:
- * "Onboard new client workflow. Can also be used to get status of any executing workflow or state machine.",
- * stateMachineArn:
- * "arn:aws:states:us-east-1:1234567890:stateMachine:my-state-machine",
- * region: "",
- * accessKeyId: "",
- * secretAccessKey: "",
- * });
- *
- *
- * const result = await toolkit.invoke({
- * input: "Onboard john doe (john@example.com) as a new client.",
- * });
- *
- * ```
- */
-export class AWSSfnToolkit extends Toolkit {
- tools: Tool[];
-
- stateMachineArn: string;
-
- asl: string;
-
- constructor(args: AWSSfnToolkitArgs & SfnConfig) {
- super();
- this.stateMachineArn = args.stateMachineArn;
- if (args.asl) {
- this.asl = args.asl;
- }
- this.tools = [
- new StartExecutionAWSSfnTool({
- name: args.name,
- description: StartExecutionAWSSfnTool.formatDescription(
- args.name,
- args.description
- ),
- stateMachineArn: args.stateMachineArn,
- }),
- new DescribeExecutionAWSSfnTool(
- Object.assign(
- args.region ? { region: args.region } : {},
- args.accessKeyId && args.secretAccessKey
- ? {
- accessKeyId: args.accessKeyId,
- secretAccessKey: args.secretAccessKey,
- }
- : {}
- )
- ),
- new SendTaskSuccessAWSSfnTool(
- Object.assign(
- args.region ? { region: args.region } : {},
- args.accessKeyId && args.secretAccessKey
- ? {
- accessKeyId: args.accessKeyId,
- secretAccessKey: args.secretAccessKey,
- }
- : {}
- )
- ),
- ];
- }
-}
-
export function createAWSSfnAgent(
llm: BaseLanguageModel,
toolkit: AWSSfnToolkit,
diff --git a/langchain/src/agents/toolkits/base.ts b/langchain/src/agents/toolkits/base.ts
index 60ead6bcb6e3..a95bd9064911 100644
--- a/langchain/src/agents/toolkits/base.ts
+++ b/langchain/src/agents/toolkits/base.ts
@@ -1,10 +1 @@
-import { Tool } from "../../tools/base.js";
-
-/**
- * Abstract base class for toolkits in LangChain. Toolkits are collections
- * of tools that agents can use. Subclasses must implement the `tools`
- * property to provide the specific tools for the toolkit.
- */
-export abstract class Toolkit {
- abstract tools: Tool[];
-}
+export * from "@langchain/community/agents/toolkits/base";
diff --git a/langchain/src/agents/toolkits/connery/index.ts b/langchain/src/agents/toolkits/connery/index.ts
index a8b54f3d54d3..e999844a9298 100644
--- a/langchain/src/agents/toolkits/connery/index.ts
+++ b/langchain/src/agents/toolkits/connery/index.ts
@@ -1,35 +1 @@
-import { Tool } from "@langchain/core/tools";
-import { Toolkit } from "../base.js";
-import { ConneryService } from "../../../tools/connery.js";
-
-/**
- * A toolkit for working with Connery actions.
- *
- * Connery is an open-source plugin infrastructure for AI.
- * Source code: https://github.com/connery-io/connery-platform
- *
- * See an example of using this toolkit here: `./examples/src/agents/connery_mrkl.ts`
- * @extends Toolkit
- */
-export class ConneryToolkit extends Toolkit {
- tools: Tool[];
-
- /**
- * Creates a ConneryToolkit instance based on the provided ConneryService instance.
- * It populates the tools property of the ConneryToolkit instance with the list of
- * available tools from the ConneryService instance.
- * @param conneryService The ConneryService instance.
- * @returns A Promise that resolves to a ConneryToolkit instance.
- */
- static async createInstance(
- conneryService: ConneryService
- ): Promise {
- const toolkit = new ConneryToolkit();
- toolkit.tools = [];
-
- const actions = await conneryService.listActions();
- toolkit.tools.push(...actions);
-
- return toolkit;
- }
-}
+export * from "@langchain/community/agents/toolkits/connery";
diff --git a/langchain/src/cache/cloudflare_kv.ts b/langchain/src/cache/cloudflare_kv.ts
index d438c7cd7cc5..b3f86e2b187e 100644
--- a/langchain/src/cache/cloudflare_kv.ts
+++ b/langchain/src/cache/cloudflare_kv.ts
@@ -1,77 +1 @@
-import type { KVNamespace } from "@cloudflare/workers-types";
-
-import { BaseCache, Generation } from "../schema/index.js";
-import {
- getCacheKey,
- serializeGeneration,
- deserializeStoredGeneration,
-} from "./base.js";
-
-/**
- * Represents a specific implementation of a caching mechanism using Cloudflare KV
- * as the underlying storage system. It extends the `BaseCache` class and
- * overrides its methods to provide the Cloudflare KV-specific logic.
- * @example
- * ```typescript
- * // Example of using OpenAI with Cloudflare KV as cache in a Cloudflare Worker
- * const cache = new CloudflareKVCache(env.KV_NAMESPACE);
- * const model = new ChatAnthropic({
- * cache,
- * });
- * const response = await model.invoke("How are you today?");
- * return new Response(JSON.stringify(response), {
- * headers: { "content-type": "application/json" },
- * });
- *
- * ```
- */
-export class CloudflareKVCache extends BaseCache {
- private binding: KVNamespace;
-
- constructor(binding: KVNamespace) {
- super();
- this.binding = binding;
- }
-
- /**
- * Retrieves data from the cache. It constructs a cache key from the given
- * `prompt` and `llmKey`, and retrieves the corresponding value from the
- * Cloudflare KV namespace.
- * @param prompt The prompt used to construct the cache key.
- * @param llmKey The LLM key used to construct the cache key.
- * @returns An array of Generations if found, null otherwise.
- */
- public async lookup(prompt: string, llmKey: string) {
- let idx = 0;
- let key = getCacheKey(prompt, llmKey, String(idx));
- let value = await this.binding.get(key);
- const generations: Generation[] = [];
-
- while (value) {
- generations.push(deserializeStoredGeneration(JSON.parse(value)));
- idx += 1;
- key = getCacheKey(prompt, llmKey, String(idx));
- value = await this.binding.get(key);
- }
-
- return generations.length > 0 ? generations : null;
- }
-
- /**
- * Updates the cache with new data. It constructs a cache key from the
- * given `prompt` and `llmKey`, and stores the `value` in the Cloudflare KV
- * namespace.
- * @param prompt The prompt used to construct the cache key.
- * @param llmKey The LLM key used to construct the cache key.
- * @param value The value to be stored in the cache.
- */
- public async update(prompt: string, llmKey: string, value: Generation[]) {
- for (let i = 0; i < value.length; i += 1) {
- const key = getCacheKey(prompt, llmKey, String(i));
- await this.binding.put(
- key,
- JSON.stringify(serializeGeneration(value[i]))
- );
- }
- }
-}
+export * from "@langchain/community/caches/cloudflare_kv";
diff --git a/langchain/src/cache/ioredis.ts b/langchain/src/cache/ioredis.ts
index de95b6248490..c2ab02d26e60 100644
--- a/langchain/src/cache/ioredis.ts
+++ b/langchain/src/cache/ioredis.ts
@@ -1,89 +1 @@
-import { Redis } from "ioredis";
-import { BaseCache, Generation } from "../schema/index.js";
-import {
- serializeGeneration,
- deserializeStoredGeneration,
- getCacheKey,
-} from "./base.js";
-
-/**
- * Cache LLM results using Redis.
- * @example
- * ```typescript
- * const model = new ChatOpenAI({
- * cache: new RedisCache(new Redis(), { ttl: 60 }),
- * });
- *
- * // Invoke the model with a prompt
- * const response = await model.invoke("Do something random!");
- * console.log(response);
- *
- * // Remember to disconnect the Redis client when done
- * await redisClient.disconnect();
- * ```
- */
-export class RedisCache extends BaseCache {
- protected redisClient: Redis;
-
- protected ttl?: number;
-
- constructor(
- redisClient: Redis,
- config?: {
- ttl?: number;
- }
- ) {
- super();
- this.redisClient = redisClient;
- this.ttl = config?.ttl;
- }
-
- /**
- * Retrieves data from the Redis server using a prompt and an LLM key. If
- * the data is not found, it returns null.
- * @param prompt The prompt used to find the data.
- * @param llmKey The LLM key used to find the data.
- * @returns The corresponding data as an array of Generation objects, or null if not found.
- */
- public async lookup(prompt: string, llmKey: string) {
- let idx = 0;
- let key = getCacheKey(prompt, llmKey, String(idx));
- let value = await this.redisClient.get(key);
- const generations: Generation[] = [];
-
- while (value) {
- const storedGeneration = JSON.parse(value);
- generations.push(deserializeStoredGeneration(storedGeneration));
- idx += 1;
- key = getCacheKey(prompt, llmKey, String(idx));
- value = await this.redisClient.get(key);
- }
-
- return generations.length > 0 ? generations : null;
- }
-
- /**
- * Updates the data in the Redis server using a prompt and an LLM key.
- * @param prompt The prompt used to store the data.
- * @param llmKey The LLM key used to store the data.
- * @param value The data to be stored, represented as an array of Generation objects.
- */
- public async update(prompt: string, llmKey: string, value: Generation[]) {
- for (let i = 0; i < value.length; i += 1) {
- const key = getCacheKey(prompt, llmKey, String(i));
- if (this.ttl !== undefined) {
- await this.redisClient.set(
- key,
- JSON.stringify(serializeGeneration(value[i])),
- "EX",
- this.ttl
- );
- } else {
- await this.redisClient.set(
- key,
- JSON.stringify(serializeGeneration(value[i]))
- );
- }
- }
- }
-}
+export * from "@langchain/community/caches/ioredis";
diff --git a/langchain/src/cache/momento.ts b/langchain/src/cache/momento.ts
index 3c452a429e45..0a24cf70f21b 100644
--- a/langchain/src/cache/momento.ts
+++ b/langchain/src/cache/momento.ts
@@ -1,173 +1 @@
-/* eslint-disable no-instanceof/no-instanceof */
-import {
- ICacheClient,
- CacheGet,
- CacheSet,
- InvalidArgumentError,
-} from "@gomomento/sdk-core";
-
-import { BaseCache, Generation } from "../schema/index.js";
-import {
- deserializeStoredGeneration,
- getCacheKey,
- serializeGeneration,
-} from "./base.js";
-import { ensureCacheExists } from "../util/momento.js";
-
-/**
- * The settings to instantiate the Momento standard cache.
- */
-export interface MomentoCacheProps {
- /**
- * The Momento cache client.
- */
- client: ICacheClient;
- /**
- * The name of the cache to use to store the data.
- */
- cacheName: string;
- /**
- * The time to live for the cache items. If not specified,
- * the cache client default is used.
- */
- ttlSeconds?: number;
- /**
- * If true, ensure that the cache exists before returning.
- * If false, the cache is not checked for existence.
- * Defaults to true.
- */
- ensureCacheExists?: true;
-}
-
-/**
- * A cache that uses Momento as the backing store.
- * See https://gomomento.com.
- * @example
- * ```typescript
- * const cache = new MomentoCache({
- * client: new CacheClient({
- * configuration: Configurations.Laptop.v1(),
- * credentialProvider: CredentialProvider.fromEnvironmentVariable({
- * environmentVariableName: "MOMENTO_API_KEY",
- * }),
- * defaultTtlSeconds: 60 * 60 * 24, // Cache TTL set to 24 hours.
- * }),
- * cacheName: "langchain",
- * });
- * // Initialize the OpenAI model with Momento cache for caching responses
- * const model = new ChatOpenAI({
- * cache,
- * });
- * await model.invoke("How are you today?");
- * const cachedValues = await cache.lookup("How are you today?", "llmKey");
- * ```
- */
-export class MomentoCache extends BaseCache {
- private client: ICacheClient;
-
- private readonly cacheName: string;
-
- private readonly ttlSeconds?: number;
-
- private constructor(props: MomentoCacheProps) {
- super();
- this.client = props.client;
- this.cacheName = props.cacheName;
-
- this.validateTtlSeconds(props.ttlSeconds);
- this.ttlSeconds = props.ttlSeconds;
- }
-
- /**
- * Create a new standard cache backed by Momento.
- *
- * @param {MomentoCacheProps} props The settings to instantiate the cache.
- * @param {ICacheClient} props.client The Momento cache client.
- * @param {string} props.cacheName The name of the cache to use to store the data.
- * @param {number} props.ttlSeconds The time to live for the cache items. If not specified,
- * the cache client default is used.
- * @param {boolean} props.ensureCacheExists If true, ensure that the cache exists before returning.
- * If false, the cache is not checked for existence. Defaults to true.
- * @throws {@link InvalidArgumentError} if {@link props.ttlSeconds} is not strictly positive.
- * @returns The Momento-backed cache.
- */
- public static async fromProps(
- props: MomentoCacheProps
- ): Promise {
- const instance = new MomentoCache(props);
- if (props.ensureCacheExists || props.ensureCacheExists === undefined) {
- await ensureCacheExists(props.client, props.cacheName);
- }
- return instance;
- }
-
- /**
- * Validate the user-specified TTL, if provided, is strictly positive.
- * @param ttlSeconds The TTL to validate.
- */
- private validateTtlSeconds(ttlSeconds?: number): void {
- if (ttlSeconds !== undefined && ttlSeconds <= 0) {
- throw new InvalidArgumentError("ttlSeconds must be positive.");
- }
- }
-
- /**
- * Lookup LLM generations in cache by prompt and associated LLM key.
- * @param prompt The prompt to lookup.
- * @param llmKey The LLM key to lookup.
- * @returns The generations associated with the prompt and LLM key, or null if not found.
- */
- public async lookup(
- prompt: string,
- llmKey: string
- ): Promise {
- const key = getCacheKey(prompt, llmKey);
- const getResponse = await this.client.get(this.cacheName, key);
-
- if (getResponse instanceof CacheGet.Hit) {
- const value = getResponse.valueString();
- const parsedValue = JSON.parse(value);
- if (!Array.isArray(parsedValue)) {
- return null;
- }
- return JSON.parse(value).map(deserializeStoredGeneration);
- } else if (getResponse instanceof CacheGet.Miss) {
- return null;
- } else if (getResponse instanceof CacheGet.Error) {
- throw getResponse.innerException();
- } else {
- throw new Error(`Unknown response type: ${getResponse.toString()}`);
- }
- }
-
- /**
- * Update the cache with the given generations.
- *
- * Note this overwrites any existing generations for the given prompt and LLM key.
- *
- * @param prompt The prompt to update.
- * @param llmKey The LLM key to update.
- * @param value The generations to store.
- */
- public async update(
- prompt: string,
- llmKey: string,
- value: Generation[]
- ): Promise {
- const key = getCacheKey(prompt, llmKey);
- const setResponse = await this.client.set(
- this.cacheName,
- key,
- JSON.stringify(value.map(serializeGeneration)),
- { ttl: this.ttlSeconds }
- );
-
- if (setResponse instanceof CacheSet.Success) {
- // pass
- } else if (setResponse instanceof CacheSet.Error) {
- throw setResponse.innerException();
- } else {
- throw new Error(`Unknown response type: ${setResponse.toString()}`);
- }
- }
-}
+export * from "@langchain/community/caches/momento";
diff --git a/langchain/src/cache/upstash_redis.ts b/langchain/src/cache/upstash_redis.ts
index 7f1660d6606d..8e1a82be82e3 100644
--- a/langchain/src/cache/upstash_redis.ts
+++ b/langchain/src/cache/upstash_redis.ts
@@ -1,91 +1 @@
-import { Redis, type RedisConfigNodejs } from "@upstash/redis";
-
-import { BaseCache, Generation, StoredGeneration } from "../schema/index.js";
-import {
- deserializeStoredGeneration,
- getCacheKey,
- serializeGeneration,
-} from "./base.js";
-
-export type UpstashRedisCacheProps = {
- /**
- * The config to use to instantiate an Upstash Redis client.
- */
- config?: RedisConfigNodejs;
- /**
- * An existing Upstash Redis client.
- */
- client?: Redis;
-};
-
-/**
- * A cache that uses Upstash as the backing store.
- * See https://docs.upstash.com/redis.
- * @example
- * ```typescript
- * const cache = new UpstashRedisCache({
- * config: {
- * url: "UPSTASH_REDIS_REST_URL",
- * token: "UPSTASH_REDIS_REST_TOKEN",
- * },
- * });
- * // Initialize the OpenAI model with Upstash Redis cache for caching responses
- * const model = new ChatOpenAI({
- * cache,
- * });
- * await model.invoke("How are you today?");
- * const cachedValues = await cache.lookup("How are you today?", "llmKey");
- * ```
- */
-export class UpstashRedisCache extends BaseCache {
- private redisClient: Redis;
-
- constructor(props: UpstashRedisCacheProps) {
- super();
- const { config, client } = props;
-
- if (client) {
- this.redisClient = client;
- } else if (config) {
- this.redisClient = new Redis(config);
- } else {
- throw new Error(
- `Upstash Redis caches require either a config object or a pre-configured client.`
- );
- }
- }
-
- /**
- * Lookup LLM generations in cache by prompt and associated LLM key.
- */
- public async lookup(prompt: string, llmKey: string) {
- let idx = 0;
- let key = getCacheKey(prompt, llmKey, String(idx));
- let value = await this.redisClient.get(key);
- const generations: Generation[] = [];
-
- while (value) {
- generations.push(deserializeStoredGeneration(value));
- idx += 1;
- key = getCacheKey(prompt, llmKey, String(idx));
- value = await this.redisClient.get(key);
- }
-
- return generations.length > 0 ? generations : null;
- }
-
- /**
- * Update the cache with the given generations.
- *
- * Note this overwrites any existing generations for the given prompt and LLM key.
- */
- public async update(prompt: string, llmKey: string, value: Generation[]) {
- for (let i = 0; i < value.length; i += 1) {
- const key = getCacheKey(prompt, llmKey, String(i));
- await this.redisClient.set(
- key,
- JSON.stringify(serializeGeneration(value[i]))
- );
- }
- }
-}
+export * from "@langchain/community/caches/upstash_redis";
diff --git a/langchain/src/callbacks/handlers/llmonitor.ts b/langchain/src/callbacks/handlers/llmonitor.ts
index 9453d62ed7ef..92fe3e48f946 100644
--- a/langchain/src/callbacks/handlers/llmonitor.ts
+++ b/langchain/src/callbacks/handlers/llmonitor.ts
@@ -1,340 +1 @@
-import monitor from "llmonitor";
-import { LLMonitorOptions, ChatMessage, cJSON } from "llmonitor/types";
-
-import { BaseRun, RunUpdate as BaseRunUpdate, KVMap } from "langsmith/schemas";
-
-import { getEnvironmentVariable } from "../../util/env.js";
-
-import {
- BaseMessage,
- ChainValues,
- Generation,
- LLMResult,
-} from "../../schema/index.js";
-import { Serialized } from "../../load/serializable.js";
-
-import { BaseCallbackHandler, BaseCallbackHandlerInput } from "../base.js";
-
-type Role = "user" | "ai" | "system" | "function" | "tool";
-
-// Langchain Helpers
-// Input can be either a single message, an array of message, or an array of array of messages (batch requests)
-
-const parseRole = (id: string[]): Role => {
- const roleHint = id[id.length - 1];
-
- if (roleHint.includes("Human")) return "user";
- if (roleHint.includes("System")) return "system";
- if (roleHint.includes("AI")) return "ai";
- if (roleHint.includes("Function")) return "function";
- if (roleHint.includes("Tool")) return "tool";
-
- return "ai";
-};
-
-type Message = BaseMessage | Generation | string;
-
-type OutputMessage = ChatMessage | string;
-
-const PARAMS_TO_CAPTURE = [
- "stop",
- "stop_sequences",
- "function_call",
- "functions",
- "tools",
- "tool_choice",
- "response_format",
-];
-
-export const convertToLLMonitorMessages = (
- input: Message | Message[] | Message[][]
-): OutputMessage | OutputMessage[] | OutputMessage[][] => {
- const parseMessage = (raw: Message): OutputMessage => {
- if (typeof raw === "string") return raw;
- // sometimes the message is nested in a "message" property
- if ("message" in raw) return parseMessage(raw.message as Message);
-
- // Serialize
- const message = JSON.parse(JSON.stringify(raw));
-
- try {
- // "id" contains an array describing the constructor, with last item actual schema type
- const role = parseRole(message.id);
-
- const obj = message.kwargs;
- const text = message.text ?? obj.content;
-
- return {
- role,
- text,
- ...(obj.additional_kwargs ?? {}),
- };
- } catch (e) {
- // if parsing fails, return the original message
- return message.text ?? message;
- }
- };
-
- if (Array.isArray(input)) {
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore Confuses the compiler
- return input.length === 1
- ? convertToLLMonitorMessages(input[0])
- : input.map(convertToLLMonitorMessages);
- }
- return parseMessage(input);
-};
-
-const parseInput = (rawInput: Record) => {
- if (!rawInput) return null;
-
- const { input, inputs, question } = rawInput;
-
- if (input) return input;
- if (inputs) return inputs;
- if (question) return question;
-
- return rawInput;
-};
-
-const parseOutput = (rawOutput: Record) => {
- if (!rawOutput) return null;
-
- const { text, output, answer, result } = rawOutput;
-
- if (text) return text;
- if (answer) return answer;
- if (output) return output;
- if (result) return result;
-
- return rawOutput;
-};
-
-const parseExtraAndName = (
- llm: Serialized,
- extraParams?: KVMap,
- metadata?: KVMap
-) => {
- const params = {
- ...(extraParams?.invocation_params ?? {}),
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore this is a valid property
- ...(llm?.kwargs ?? {}),
- ...(metadata || {}),
- };
-
- const { model, model_name, modelName, model_id, userId, userProps, ...rest } =
- params;
-
- const name = model || modelName || model_name || model_id || llm.id.at(-1);
-
- // Filter rest to only include params we want to capture
- const extra = Object.fromEntries(
- Object.entries(rest).filter(
- ([key]) =>
- PARAMS_TO_CAPTURE.includes(key) ||
- ["string", "number", "boolean"].includes(typeof rest[key])
- )
- ) as cJSON;
-
- return { name, extra, userId, userProps };
-};
-
-export interface Run extends BaseRun {
- id: string;
- child_runs: this[];
- child_execution_order: number;
-}
-
-export interface RunUpdate extends BaseRunUpdate {
- events: BaseRun["events"];
-}
-
-export interface LLMonitorHandlerFields
- extends BaseCallbackHandlerInput,
- LLMonitorOptions {}
-
-export class LLMonitorHandler
- extends BaseCallbackHandler
- implements LLMonitorHandlerFields
-{
- name = "llmonitor_handler";
-
- monitor: typeof monitor;
-
- constructor(fields: LLMonitorHandlerFields = {}) {
- super(fields);
-
- this.monitor = monitor;
-
- if (fields) {
- const { appId, apiUrl, verbose } = fields;
-
- this.monitor.init({
- verbose,
- appId: appId ?? getEnvironmentVariable("LLMONITOR_APP_ID"),
- apiUrl: apiUrl ?? getEnvironmentVariable("LLMONITOR_API_URL"),
- });
- }
- }
-
- async handleLLMStart(
- llm: Serialized,
- prompts: string[],
- runId: string,
- parentRunId?: string,
- extraParams?: KVMap,
- tags?: string[],
- metadata?: KVMap
- ): Promise {
- const { name, extra, userId, userProps } = parseExtraAndName(
- llm,
- extraParams,
- metadata
- );
-
- await this.monitor.trackEvent("llm", "start", {
- runId,
- parentRunId,
- name,
- input: convertToLLMonitorMessages(prompts),
- extra,
- userId,
- userProps,
- tags,
- runtime: "langchain-js",
- });
- }
-
- async handleChatModelStart(
- llm: Serialized,
- messages: BaseMessage[][],
- runId: string,
- parentRunId?: string,
- extraParams?: KVMap,
- tags?: string[],
- metadata?: KVMap
- ): Promise {
- const { name, extra, userId, userProps } = parseExtraAndName(
- llm,
- extraParams,
- metadata
- );
-
- await this.monitor.trackEvent("llm", "start", {
- runId,
- parentRunId,
- name,
- input: convertToLLMonitorMessages(messages),
- extra,
- userId,
- userProps,
- tags,
- runtime: "langchain-js",
- });
- }
-
- async handleLLMEnd(output: LLMResult, runId: string): Promise {
- const { generations, llmOutput } = output;
-
- await this.monitor.trackEvent("llm", "end", {
- runId,
- output: convertToLLMonitorMessages(generations),
- tokensUsage: {
- completion: llmOutput?.tokenUsage?.completionTokens,
- prompt: llmOutput?.tokenUsage?.promptTokens,
- },
- });
- }
-
- async handleLLMError(error: Error, runId: string): Promise {
- await this.monitor.trackEvent("llm", "error", {
- runId,
- error,
- });
- }
-
- async handleChainStart(
- chain: Serialized,
- inputs: ChainValues,
- runId: string,
- parentRunId?: string,
- tags?: string[],
- metadata?: KVMap
- ): Promise {
- const { agentName, userId, userProps, ...rest } = metadata || {};
-
- // allow the user to specify an agent name
- const name = agentName || chain.id.at(-1);
-
- // Attempt to automatically detect if this is an agent or chain
- const runType =
- agentName || ["AgentExecutor", "PlanAndExecute"].includes(name)
- ? "agent"
- : "chain";
-
- await this.monitor.trackEvent(runType, "start", {
- runId,
- parentRunId,
- name,
- userId,
- userProps,
- input: parseInput(inputs) as cJSON,
- extra: rest,
- tags,
- runtime: "langchain-js",
- });
- }
-
- async handleChainEnd(outputs: ChainValues, runId: string): Promise {
- await this.monitor.trackEvent("chain", "end", {
- runId,
- output: parseOutput(outputs) as cJSON,
- });
- }
-
- async handleChainError(error: Error, runId: string): Promise {
- await this.monitor.trackEvent("chain", "error", {
- runId,
- error,
- });
- }
-
- async handleToolStart(
- tool: Serialized,
- input: string,
- runId: string,
- parentRunId?: string,
- tags?: string[],
- metadata?: KVMap
- ): Promise {
- const { toolName, userId, userProps, ...rest } = metadata || {};
- const name = toolName || tool.id.at(-1);
-
- await this.monitor.trackEvent("tool", "start", {
- runId,
- parentRunId,
- name,
- userId,
- userProps,
- input,
- extra: rest,
- tags,
- runtime: "langchain-js",
- });
- }
-
- async handleToolEnd(output: string, runId: string): Promise {
- await this.monitor.trackEvent("tool", "end", {
- runId,
- output,
- });
- }
-
- async handleToolError(error: Error, runId: string): Promise {
- await this.monitor.trackEvent("tool", "error", {
- runId,
- error,
- });
- }
-}
+export * from "@langchain/community/callbacks/handlers/llmonitor";
diff --git a/langchain/src/callbacks/tests/llmonitor.int.test.ts b/langchain/src/callbacks/tests/llmonitor.int.test.ts
index eb796840d66c..62c589f501d8 100644
--- a/langchain/src/callbacks/tests/llmonitor.int.test.ts
+++ b/langchain/src/callbacks/tests/llmonitor.int.test.ts
@@ -16,7 +16,7 @@ import { Calculator } from "../../tools/calculator.js";
import { initializeAgentExecutorWithOptions } from "../../agents/initialize.js";
-test("Test traced agent with openai functions", async () => {
+test.skip("Test traced agent with openai functions", async () => {
const tools = [new Calculator()];
const chat = new ChatOpenAI({ modelName: "gpt-3.5-turbo", temperature: 0 });
@@ -41,7 +41,7 @@ test("Test traced agent with openai functions", async () => {
console.log(result);
});
-test("Test traced chain with tags", async () => {
+test.skip("Test traced chain with tags", async () => {
const llm = new OpenAI();
const qaPrompt = new PromptTemplate({
template: "Q: {question} A:",
@@ -75,7 +75,7 @@ test("Test traced chain with tags", async () => {
);
});
-test("Test traced chat call with tags", async () => {
+test.skip("Test traced chat call with tags", async () => {
const chat = new ChatOpenAI({
callbacks: [new LLMonitorHandler({ verbose: true })],
});
diff --git a/langchain/src/chains/openai_functions/openapi.ts b/langchain/src/chains/openai_functions/openapi.ts
index 06eb92ad4995..5306eef626db 100644
--- a/langchain/src/chains/openai_functions/openapi.ts
+++ b/langchain/src/chains/openai_functions/openapi.ts
@@ -1,4 +1,4 @@
-import type { OpenAI as OpenAIClient } from "openai";
+import type { OpenAIClient } from "@langchain/openai";
import { JsonSchema7ObjectType } from "zod-to-json-schema/src/parsers/object.js";
import { JsonSchema7ArrayType } from "zod-to-json-schema/src/parsers/array.js";
import { JsonSchema7Type } from "zod-to-json-schema/src/parseDef.js";
diff --git a/langchain/src/chains/openai_moderation.ts b/langchain/src/chains/openai_moderation.ts
index 862552099405..2474baaab0ba 100644
--- a/langchain/src/chains/openai_moderation.ts
+++ b/langchain/src/chains/openai_moderation.ts
@@ -1,4 +1,4 @@
-import { type ClientOptions, OpenAI as OpenAIClient } from "openai";
+import { type ClientOptions, OpenAIClient } from "@langchain/openai";
import { BaseChain, ChainInputs } from "./base.js";
import { ChainValues } from "../schema/index.js";
import { AsyncCaller, AsyncCallerParams } from "../util/async_caller.js";
diff --git a/langchain/src/chains/tests/sql_db_chain.int.test.ts b/langchain/src/chains/tests/sql_db_chain.int.test.ts
index b01b6f802f11..c90568016bfa 100644
--- a/langchain/src/chains/tests/sql_db_chain.int.test.ts
+++ b/langchain/src/chains/tests/sql_db_chain.int.test.ts
@@ -106,7 +106,7 @@ Aliquam ultricies, sapien a porta luctus, dolor nibh dignissim erat, dictum luct
Aliquam ex velit, porta sit amet augue vulputate, rhoncus fermentum magna. Integer non elementum augue. Phasellus rhoncus nisl nec magna lacinia vulputate. Suspendisse diam nibh, egestas a porta a, pellentesque ut nisl. Donec tempus ligula at leo convallis consequat. Duis sapien lorem, lobortis ac nisl dapibus, bibendum mollis lorem. Sed congue porttitor ex, eget scelerisque ligula consectetur quis. Mauris felis mauris, sodales quis nunc non, condimentum eleifend quam. Ut vitae viverra lorem. Vivamus lacinia et dolor vitae cursus. Proin faucibus venenatis enim vitae tincidunt. Sed sed venenatis leo.
`;
-test("Test token limite SqlDatabaseChain", async () => {
+test.skip("Test token limit SqlDatabaseChain", async () => {
const datasource = new DataSource({
type: "sqlite",
database: ":memory:",
diff --git a/langchain/src/chat_models/baiduwenxin.ts b/langchain/src/chat_models/baiduwenxin.ts
index 060da0298e76..61ffe21de4d4 100644
--- a/langchain/src/chat_models/baiduwenxin.ts
+++ b/langchain/src/chat_models/baiduwenxin.ts
@@ -1,542 +1 @@
-import { BaseChatModel, BaseChatModelParams } from "./base.js";
-import {
- AIMessage,
- BaseMessage,
- ChatGeneration,
- ChatMessage,
- ChatResult,
-} from "../schema/index.js";
-import { CallbackManagerForLLMRun } from "../callbacks/manager.js";
-import { getEnvironmentVariable } from "../util/env.js";
-
-/**
- * Type representing the role of a message in the Wenxin chat model.
- */
-export type WenxinMessageRole = "assistant" | "user";
-
-/**
- * Interface representing a message in the Wenxin chat model.
- */
-interface WenxinMessage {
- role: WenxinMessageRole;
- content: string;
-}
-
-/**
- * Interface representing the usage of tokens in a chat completion.
- */
-interface TokenUsage {
- completionTokens?: number;
- promptTokens?: number;
- totalTokens?: number;
-}
-
-/**
- * Interface representing a request for a chat completion.
- */
-interface ChatCompletionRequest {
- messages: WenxinMessage[];
- stream?: boolean;
- user_id?: string;
- temperature?: number;
- top_p?: number;
- penalty_score?: number;
- system?: string;
-}
-
-/**
- * Interface representing a response from a chat completion.
- */
-interface ChatCompletionResponse {
- id: string;
- object: string;
- created: number;
- result: string;
- need_clear_history: boolean;
- usage: TokenUsage;
-}
-
-/**
- * Interface defining the input to the ChatBaiduWenxin class.
- */
-declare interface BaiduWenxinChatInput {
- /** Model name to use. Available options are: ERNIE-Bot, ERNIE-Bot-turbo, ERNIE-Bot-4
- * @default "ERNIE-Bot-turbo"
- */
- modelName: string;
-
- /** Whether to stream the results or not. Defaults to false. */
- streaming?: boolean;
-
- /** Messages to pass as a prefix to the prompt */
- prefixMessages?: WenxinMessage[];
-
- /**
- * ID of the end-user who made requests.
- */
- userId?: string;
-
- /**
- * API key to use when making requests. Defaults to the value of
- * `BAIDU_API_KEY` environment variable.
- */
- baiduApiKey?: string;
-
- /**
- * Secret key to use when making requests. Defaults to the value of
- * `BAIDU_SECRET_KEY` environment variable.
- */
- baiduSecretKey?: string;
-
- /** Amount of randomness injected into the response. Ranges
- * from 0 to 1 (0 is not included). Use temp closer to 0 for analytical /
- * multiple choice, and temp closer to 1 for creative
- * and generative tasks. Defaults to 0.95.
- */
- temperature?: number;
-
- /** Total probability mass of tokens to consider at each step. Range
- * from 0 to 1.0. Defaults to 0.8.
- */
- topP?: number;
-
- /** Penalizes repeated tokens according to frequency. Range
- * from 1.0 to 2.0. Defaults to 1.0.
- */
- penaltyScore?: number;
-}
-
-/**
- * Function that extracts the custom role of a generic chat message.
- * @param message Chat message from which to extract the custom role.
- * @returns The custom role of the chat message.
- */
-function extractGenericMessageCustomRole(message: ChatMessage) {
- if (message.role !== "assistant" && message.role !== "user") {
- console.warn(`Unknown message role: ${message.role}`);
- }
-
- return message.role as WenxinMessageRole;
-}
-
-/**
- * Function that converts a base message to a Wenxin message role.
- * @param message Base message to convert.
- * @returns The Wenxin message role.
- */
-function messageToWenxinRole(message: BaseMessage): WenxinMessageRole {
- const type = message._getType();
- switch (type) {
- case "ai":
- return "assistant";
- case "human":
- return "user";
- case "system":
- throw new Error("System messages should not be here");
- case "function":
- throw new Error("Function messages not supported");
- case "generic": {
- if (!ChatMessage.isInstance(message))
- throw new Error("Invalid generic chat message");
- return extractGenericMessageCustomRole(message);
- }
- default:
- throw new Error(`Unknown message type: ${type}`);
- }
-}
-
-/**
- * Wrapper around Baidu ERNIE large language models that use the Chat endpoint.
- *
- * To use you should have the `BAIDU_API_KEY` and `BAIDU_SECRET_KEY`
- * environment variable set.
- *
- * @augments BaseLLM
- * @augments BaiduERNIEInput
- * @example
- * ```typescript
- * const ernieTurbo = new ChatBaiduWenxin({
- * baiduApiKey: "YOUR-API-KEY",
- * baiduSecretKey: "YOUR-SECRET-KEY",
- * });
- *
- * const ernie = new ChatBaiduWenxin({
- * modelName: "ERNIE-Bot",
- * temperature: 1,
- * baiduApiKey: "YOUR-API-KEY",
- * baiduSecretKey: "YOUR-SECRET-KEY",
- * });
- *
- * const messages = [new HumanMessage("Hello")];
- *
- * let res = await ernieTurbo.call(messages);
- *
- * res = await ernie.call(messages);
- * ```
- */
-export class ChatBaiduWenxin
- extends BaseChatModel
- implements BaiduWenxinChatInput
-{
- static lc_name() {
- return "ChatBaiduWenxin";
- }
-
- get callKeys(): string[] {
- return ["stop", "signal", "options"];
- }
-
- get lc_secrets(): { [key: string]: string } | undefined {
- return {
- baiduApiKey: "BAIDU_API_KEY",
- baiduSecretKey: "BAIDU_SECRET_KEY",
- };
- }
-
- get lc_aliases(): { [key: string]: string } | undefined {
- return undefined;
- }
-
- lc_serializable = true;
-
- baiduApiKey?: string;
-
- baiduSecretKey?: string;
-
- accessToken: string;
-
- streaming = false;
-
- prefixMessages?: WenxinMessage[];
-
- userId?: string;
-
- modelName = "ERNIE-Bot-turbo";
-
- apiUrl: string;
-
- temperature?: number | undefined;
-
- topP?: number | undefined;
-
- penaltyScore?: number | undefined;
-
- constructor(fields?: Partial & BaseChatModelParams) {
- super(fields ?? {});
-
- this.baiduApiKey =
- fields?.baiduApiKey ?? getEnvironmentVariable("BAIDU_API_KEY");
- if (!this.baiduApiKey) {
- throw new Error("Baidu API key not found");
- }
-
- this.baiduSecretKey =
- fields?.baiduSecretKey ?? getEnvironmentVariable("BAIDU_SECRET_KEY");
- if (!this.baiduSecretKey) {
- throw new Error("Baidu Secret key not found");
- }
-
- this.streaming = fields?.streaming ?? this.streaming;
- this.prefixMessages = fields?.prefixMessages ?? this.prefixMessages;
- this.userId = fields?.userId ?? this.userId;
- this.temperature = fields?.temperature ?? this.temperature;
- this.topP = fields?.topP ?? this.topP;
- this.penaltyScore = fields?.penaltyScore ?? this.penaltyScore;
-
- this.modelName = fields?.modelName ?? this.modelName;
-
- if (this.modelName === "ERNIE-Bot") {
- this.apiUrl =
- "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions";
- } else if (this.modelName === "ERNIE-Bot-turbo") {
- this.apiUrl =
- "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/eb-instant";
- } else if (this.modelName === "ERNIE-Bot-4") {
- this.apiUrl =
- "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions_pro";
- } else {
- throw new Error(`Invalid model name: ${this.modelName}`);
- }
- }
-
- /**
- * Method that retrieves the access token for making requests to the Baidu
- * API.
- * @param options Optional parsed call options.
- * @returns The access token for making requests to the Baidu API.
- */
- async getAccessToken(options?: this["ParsedCallOptions"]) {
- 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",
- },
- signal: options?.signal,
- });
- 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;
- }
-
- /**
- * Get the parameters used to invoke the model
- */
- invocationParams(): Omit {
- return {
- stream: this.streaming,
- user_id: this.userId,
- temperature: this.temperature,
- top_p: this.topP,
- penalty_score: this.penaltyScore,
- };
- }
-
- /**
- * Get the identifying parameters for the model
- */
- identifyingParams() {
- return {
- model_name: this.modelName,
- ...this.invocationParams(),
- };
- }
-
- /** @ignore */
- async _generate(
- messages: BaseMessage[],
- options?: this["ParsedCallOptions"],
- runManager?: CallbackManagerForLLMRun
- ): Promise {
- const tokenUsage: TokenUsage = {};
-
- const params = this.invocationParams();
-
- // Wenxin requires the system message to be put in the params, not messages array
- const systemMessage = messages.find(
- (message) => message._getType() === "system"
- );
- if (systemMessage) {
- // eslint-disable-next-line no-param-reassign
- messages = messages.filter((message) => message !== systemMessage);
- params.system = systemMessage.text;
- }
- const messagesMapped: WenxinMessage[] = messages.map((message) => ({
- role: messageToWenxinRole(message),
- content: message.text,
- }));
-
- const data = params.stream
- ? await new Promise((resolve, reject) => {
- let response: ChatCompletionResponse;
- let rejected = false;
- let resolved = false;
- this.completionWithRetry(
- {
- ...params,
- messages: messagesMapped,
- },
- true,
- options?.signal,
- (event) => {
- const data = JSON.parse(event.data);
-
- if (data?.error_code) {
- if (rejected) {
- return;
- }
- rejected = true;
- reject(new Error(data?.error_msg));
- return;
- }
-
- const message = data as {
- id: string;
- object: string;
- created: number;
- sentence_id?: number;
- is_end: boolean;
- result: string;
- need_clear_history: boolean;
- usage: TokenUsage;
- };
-
- // on the first message set the response properties
- if (!response) {
- response = {
- id: message.id,
- object: message.object,
- created: message.created,
- result: message.result,
- need_clear_history: message.need_clear_history,
- usage: message.usage,
- };
- } else {
- response.result += message.result;
- response.created = message.created;
- response.need_clear_history = message.need_clear_history;
- response.usage = message.usage;
- }
-
- // TODO this should pass part.index to the callback
- // when that's supported there
- // eslint-disable-next-line no-void
- void runManager?.handleLLMNewToken(message.result ?? "");
-
- if (message.is_end) {
- if (resolved || rejected) {
- return;
- }
- resolved = true;
- resolve(response);
- }
- }
- ).catch((error) => {
- if (!rejected) {
- rejected = true;
- reject(error);
- }
- });
- })
- : await this.completionWithRetry(
- {
- ...params,
- messages: messagesMapped,
- },
- false,
- options?.signal
- ).then((data) => {
- if (data?.error_code) {
- throw new Error(data?.error_msg);
- }
- return data;
- });
-
- const {
- completion_tokens: completionTokens,
- prompt_tokens: promptTokens,
- total_tokens: totalTokens,
- } = data.usage ?? {};
-
- if (completionTokens) {
- tokenUsage.completionTokens =
- (tokenUsage.completionTokens ?? 0) + completionTokens;
- }
-
- if (promptTokens) {
- tokenUsage.promptTokens = (tokenUsage.promptTokens ?? 0) + promptTokens;
- }
-
- if (totalTokens) {
- tokenUsage.totalTokens = (tokenUsage.totalTokens ?? 0) + totalTokens;
- }
-
- const generations: ChatGeneration[] = [];
- const text = data.result ?? "";
- generations.push({
- text,
- message: new AIMessage(text),
- });
- return {
- generations,
- llmOutput: { tokenUsage },
- };
- }
-
- /** @ignore */
- async completionWithRetry(
- request: ChatCompletionRequest,
- stream: boolean,
- signal?: AbortSignal,
- onmessage?: (event: MessageEvent) => void
- ) {
- // The first run will get the accessToken
- if (!this.accessToken) {
- this.accessToken = await this.getAccessToken();
- }
-
- const makeCompletionRequest = async () => {
- const url = `${this.apiUrl}?access_token=${this.accessToken}`;
- const response = await fetch(url, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- },
- body: JSON.stringify(request),
- signal,
- });
-
- if (!stream) {
- return response.json();
- } else {
- if (response.body) {
- // response will not be a stream if an error occurred
- if (
- !response.headers
- .get("content-type")
- ?.startsWith("text/event-stream")
- ) {
- onmessage?.(
- new MessageEvent("message", {
- data: await response.text(),
- })
- );
- return;
- }
-
- const reader = response.body.getReader();
-
- const decoder = new TextDecoder("utf-8");
- let data = "";
-
- let continueReading = true;
- while (continueReading) {
- const { done, value } = await reader.read();
- if (done) {
- continueReading = false;
- break;
- }
- data += decoder.decode(value);
-
- let continueProcessing = true;
- while (continueProcessing) {
- const newlineIndex = data.indexOf("\n");
- if (newlineIndex === -1) {
- continueProcessing = false;
- break;
- }
- const line = data.slice(0, newlineIndex);
- data = data.slice(newlineIndex + 1);
-
- if (line.startsWith("data:")) {
- const event = new MessageEvent("message", {
- data: line.slice("data:".length).trim(),
- });
- onmessage?.(event);
- }
- }
- }
- }
- }
- };
- return this.caller.call(makeCompletionRequest);
- }
-
- _llmType() {
- return "baiduwenxin";
- }
-
- /** @ignore */
- _combineLLMOutput() {
- return [];
- }
-}
+export * from "@langchain/community/chat_models/baiduwenxin";
diff --git a/langchain/src/chat_models/bedrock/index.ts b/langchain/src/chat_models/bedrock/index.ts
index 04fabc096d00..a78523c28a2b 100644
--- a/langchain/src/chat_models/bedrock/index.ts
+++ b/langchain/src/chat_models/bedrock/index.ts
@@ -1,38 +1 @@
-import { defaultProvider } from "@aws-sdk/credential-provider-node";
-import { BaseBedrockInput } from "../../util/bedrock.js";
-import { BedrockChat as BaseBedrockChat } from "./web.js";
-import { BaseChatModelParams } from "../base.js";
-
-/**
- * @example
- * ```typescript
- * const model = new BedrockChat({
- * model: "anthropic.claude-v2",
- * region: "us-east-1",
- * });
- * const res = await model.invoke([{ content: "Tell me a joke" }]);
- * console.log(res);
- * ```
- */
-export class BedrockChat extends BaseBedrockChat {
- static lc_name() {
- return "BedrockChat";
- }
-
- constructor(fields?: Partial & BaseChatModelParams) {
- super({
- ...fields,
- credentials: fields?.credentials ?? defaultProvider(),
- });
- }
-}
-
-export {
- convertMessagesToPromptAnthropic,
- convertMessagesToPrompt,
-} from "./web.js";
-
-/**
- * @deprecated Use `BedrockChat` instead.
- */
-export const ChatBedrock = BedrockChat;
+export * from "@langchain/community/chat_models/bedrock";
diff --git a/langchain/src/chat_models/bedrock/web.ts b/langchain/src/chat_models/bedrock/web.ts
index 0431f5baa359..9ef97f768f8a 100644
--- a/langchain/src/chat_models/bedrock/web.ts
+++ b/langchain/src/chat_models/bedrock/web.ts
@@ -1,431 +1 @@
-import { SignatureV4 } from "@smithy/signature-v4";
-import { HttpRequest } from "@smithy/protocol-http";
-import { EventStreamCodec } from "@smithy/eventstream-codec";
-import { fromUtf8, toUtf8 } from "@smithy/util-utf8";
-import { Sha256 } from "@aws-crypto/sha256-js";
-
-import {
- BaseBedrockInput,
- BedrockLLMInputOutputAdapter,
- type CredentialType,
-} from "../../util/bedrock.js";
-import { getEnvironmentVariable } from "../../util/env.js";
-import { SimpleChatModel, BaseChatModelParams } from "../base.js";
-import { CallbackManagerForLLMRun } from "../../callbacks/manager.js";
-import {
- AIMessageChunk,
- BaseMessage,
- AIMessage,
- ChatGenerationChunk,
- ChatMessage,
-} from "../../schema/index.js";
-import type { SerializedFields } from "../../load/map_keys.js";
-
-function convertOneMessageToText(
- message: BaseMessage,
- humanPrompt: string,
- aiPrompt: string
-): string {
- if (message._getType() === "human") {
- return `${humanPrompt} ${message.content}`;
- } else if (message._getType() === "ai") {
- return `${aiPrompt} ${message.content}`;
- } else if (message._getType() === "system") {
- return `${humanPrompt} ${message.content}`;
- } else if (ChatMessage.isInstance(message)) {
- return `\n\n${
- message.role[0].toUpperCase() + message.role.slice(1)
- }: {message.content}`;
- }
- throw new Error(`Unknown role: ${message._getType()}`);
-}
-
-export function convertMessagesToPromptAnthropic(
- messages: BaseMessage[],
- humanPrompt = "\n\nHuman:",
- aiPrompt = "\n\nAssistant:"
-): string {
- const messagesCopy = [...messages];
-
- if (
- messagesCopy.length === 0 ||
- messagesCopy[messagesCopy.length - 1]._getType() !== "ai"
- ) {
- messagesCopy.push(new AIMessage({ content: "" }));
- }
-
- return messagesCopy
- .map((message) => convertOneMessageToText(message, humanPrompt, aiPrompt))
- .join("");
-}
-
-/**
- * Function that converts an array of messages into a single string prompt
- * that can be used as input for a chat model. It delegates the conversion
- * logic to the appropriate provider-specific function.
- * @param messages Array of messages to be converted.
- * @param options Options to be used during the conversion.
- * @returns A string prompt that can be used as input for a chat model.
- */
-export function convertMessagesToPrompt(
- messages: BaseMessage[],
- provider: string
-): string {
- if (provider === "anthropic") {
- return convertMessagesToPromptAnthropic(messages);
- }
- throw new Error(`Provider ${provider} does not support chat.`);
-}
-
-/**
- * A type of Large Language Model (LLM) that interacts with the Bedrock
- * service. It extends the base `LLM` class and implements the
- * `BaseBedrockInput` interface. The class is designed to authenticate and
- * interact with the Bedrock service, which is a part of Amazon Web
- * Services (AWS). It uses AWS credentials for authentication and can be
- * configured with various parameters such as the model to use, the AWS
- * region, and the maximum number of tokens to generate.
- * @example
- * ```typescript
- * const model = new BedrockChat({
- * model: "anthropic.claude-v2",
- * region: "us-east-1",
- * });
- * const res = await model.invoke([{ content: "Tell me a joke" }]);
- * console.log(res);
- * ```
- */
-export class BedrockChat extends SimpleChatModel implements BaseBedrockInput {
- model = "amazon.titan-tg1-large";
-
- region: string;
-
- credentials: CredentialType;
-
- temperature?: number | undefined = undefined;
-
- maxTokens?: number | undefined = undefined;
-
- fetchFn: typeof fetch;
-
- endpointHost?: string;
-
- /** @deprecated */
- stopSequences?: string[];
-
- modelKwargs?: Record;
-
- codec: EventStreamCodec = new EventStreamCodec(toUtf8, fromUtf8);
-
- streaming = false;
-
- lc_serializable = true;
-
- get lc_aliases(): Record {
- return {
- model: "model_id",
- region: "region_name",
- };
- }
-
- get lc_secrets(): { [key: string]: string } | undefined {
- return {
- "credentials.accessKeyId": "BEDROCK_AWS_ACCESS_KEY_ID",
- "credentials.secretAccessKey": "BEDROCK_AWS_SECRET_ACCESS_KEY",
- };
- }
-
- get lc_attributes(): SerializedFields | undefined {
- return { region: this.region };
- }
-
- _llmType() {
- return "bedrock";
- }
-
- static lc_name() {
- return "BedrockChat";
- }
-
- constructor(fields?: Partial & BaseChatModelParams) {
- super(fields ?? {});
-
- this.model = fields?.model ?? this.model;
- const allowedModels = ["ai21", "anthropic", "amazon", "cohere", "meta"];
- if (!allowedModels.includes(this.model.split(".")[0])) {
- throw new Error(
- `Unknown model: '${this.model}', only these are supported: ${allowedModels}`
- );
- }
- const region =
- fields?.region ?? getEnvironmentVariable("AWS_DEFAULT_REGION");
- if (!region) {
- throw new Error(
- "Please set the AWS_DEFAULT_REGION environment variable or pass it to the constructor as the region field."
- );
- }
- this.region = region;
-
- const credentials = fields?.credentials;
- if (!credentials) {
- throw new Error(
- "Please set the AWS credentials in the 'credentials' field."
- );
- }
- this.credentials = credentials;
-
- this.temperature = fields?.temperature ?? this.temperature;
- this.maxTokens = fields?.maxTokens ?? this.maxTokens;
- this.fetchFn = fields?.fetchFn ?? fetch.bind(globalThis);
- this.endpointHost = fields?.endpointHost ?? fields?.endpointUrl;
- this.stopSequences = fields?.stopSequences;
- this.modelKwargs = fields?.modelKwargs;
- this.streaming = fields?.streaming ?? this.streaming;
- }
-
- /** Call out to Bedrock service model.
- Arguments:
- prompt: The prompt to pass into the model.
-
- Returns:
- The string generated by the model.
-
- Example:
- response = model.call("Tell me a joke.")
- */
- async _call(
- messages: BaseMessage[],
- options: this["ParsedCallOptions"],
- runManager?: CallbackManagerForLLMRun
- ): Promise {
- const service = "bedrock-runtime";
- const endpointHost =
- this.endpointHost ?? `${service}.${this.region}.amazonaws.com`;
- const provider = this.model.split(".")[0];
- if (this.streaming) {
- const stream = this._streamResponseChunks(messages, options, runManager);
- let finalResult: ChatGenerationChunk | undefined;
- for await (const chunk of stream) {
- if (finalResult === undefined) {
- finalResult = chunk;
- } else {
- finalResult = finalResult.concat(chunk);
- }
- }
- const messageContent = finalResult?.message.content;
- if (messageContent && typeof messageContent !== "string") {
- throw new Error(
- "Non-string output for ChatBedrock is currently not supported."
- );
- }
- return messageContent ?? "";
- }
-
- const response = await this._signedFetch(messages, options, {
- bedrockMethod: "invoke",
- endpointHost,
- provider,
- });
- const json = await response.json();
- if (!response.ok) {
- throw new Error(
- `Error ${response.status}: ${json.message ?? JSON.stringify(json)}`
- );
- }
- const text = BedrockLLMInputOutputAdapter.prepareOutput(provider, json);
- return text;
- }
-
- async _signedFetch(
- messages: BaseMessage[],
- options: this["ParsedCallOptions"],
- fields: {
- bedrockMethod: "invoke" | "invoke-with-response-stream";
- endpointHost: string;
- provider: string;
- }
- ) {
- const { bedrockMethod, endpointHost, provider } = fields;
- const inputBody = BedrockLLMInputOutputAdapter.prepareInput(
- provider,
- convertMessagesToPromptAnthropic(messages),
- this.maxTokens,
- this.temperature,
- options.stop ?? this.stopSequences,
- this.modelKwargs,
- fields.bedrockMethod
- );
-
- const url = new URL(
- `https://${endpointHost}/model/${this.model}/${bedrockMethod}`
- );
-
- const request = new HttpRequest({
- hostname: url.hostname,
- path: url.pathname,
- protocol: url.protocol,
- method: "POST", // method must be uppercase
- body: JSON.stringify(inputBody),
- query: Object.fromEntries(url.searchParams.entries()),
- headers: {
- // host is required by AWS Signature V4: https://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
- host: url.host,
- accept: "application/json",
- "content-type": "application/json",
- },
- });
-
- const signer = new SignatureV4({
- credentials: this.credentials,
- service: "bedrock",
- region: this.region,
- sha256: Sha256,
- });
-
- const signedRequest = await signer.sign(request);
-
- // Send request to AWS using the low-level fetch API
- const response = await this.caller.callWithOptions(
- { signal: options.signal },
- async () =>
- this.fetchFn(url, {
- headers: signedRequest.headers,
- body: signedRequest.body,
- method: signedRequest.method,
- })
- );
- return response;
- }
-
- async *_streamResponseChunks(
- messages: BaseMessage[],
- options: this["ParsedCallOptions"],
- runManager?: CallbackManagerForLLMRun
- ): AsyncGenerator {
- const provider = this.model.split(".")[0];
- const service = "bedrock-runtime";
-
- const endpointHost =
- this.endpointHost ?? `${service}.${this.region}.amazonaws.com`;
-
- const bedrockMethod =
- provider === "anthropic" || provider === "cohere" || provider === "meta"
- ? "invoke-with-response-stream"
- : "invoke";
-
- const response = await this._signedFetch(messages, options, {
- bedrockMethod,
- endpointHost,
- provider,
- });
-
- if (response.status < 200 || response.status >= 300) {
- throw Error(
- `Failed to access underlying url '${endpointHost}': got ${
- response.status
- } ${response.statusText}: ${await response.text()}`
- );
- }
-
- if (
- provider === "anthropic" ||
- provider === "cohere" ||
- provider === "meta"
- ) {
- const reader = response.body?.getReader();
- const decoder = new TextDecoder();
- for await (const chunk of this._readChunks(reader)) {
- const event = this.codec.decode(chunk);
- if (
- (event.headers[":event-type"] !== undefined &&
- event.headers[":event-type"].value !== "chunk") ||
- event.headers[":content-type"].value !== "application/json"
- ) {
- throw Error(`Failed to get event chunk: got ${chunk}`);
- }
- const body = JSON.parse(decoder.decode(event.body));
- if (body.message) {
- throw new Error(body.message);
- }
- if (body.bytes !== undefined) {
- const chunkResult = JSON.parse(
- decoder.decode(
- Uint8Array.from(atob(body.bytes), (m) => m.codePointAt(0) ?? 0)
- )
- );
- const text = BedrockLLMInputOutputAdapter.prepareOutput(
- provider,
- chunkResult
- );
- yield new ChatGenerationChunk({
- text,
- message: new AIMessageChunk({ content: text }),
- });
- // eslint-disable-next-line no-void
- void runManager?.handleLLMNewToken(text);
- }
- }
- } else {
- const json = await response.json();
- const text = BedrockLLMInputOutputAdapter.prepareOutput(provider, json);
- yield new ChatGenerationChunk({
- text,
- message: new AIMessageChunk({ content: text }),
- });
- // eslint-disable-next-line no-void
- void runManager?.handleLLMNewToken(text);
- }
- }
-
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- _readChunks(reader: any) {
- function _concatChunks(a: Uint8Array, b: Uint8Array) {
- const newBuffer = new Uint8Array(a.length + b.length);
- newBuffer.set(a);
- newBuffer.set(b, a.length);
- return newBuffer;
- }
-
- function getMessageLength(buffer: Uint8Array) {
- if (buffer.byteLength === 0) return 0;
- const view = new DataView(
- buffer.buffer,
- buffer.byteOffset,
- buffer.byteLength
- );
-
- return view.getUint32(0, false);
- }
-
- return {
- async *[Symbol.asyncIterator]() {
- let readResult = await reader.read();
-
- let buffer: Uint8Array = new Uint8Array(0);
- while (!readResult.done) {
- const chunk: Uint8Array = readResult.value;
-
- buffer = _concatChunks(buffer, chunk);
- let messageLength = getMessageLength(buffer);
-
- while (buffer.byteLength > 0 && buffer.byteLength >= messageLength) {
- yield buffer.slice(0, messageLength);
- buffer = buffer.slice(messageLength);
- messageLength = getMessageLength(buffer);
- }
-
- readResult = await reader.read();
- }
- },
- };
- }
-
- _combineLLMOutput() {
- return {};
- }
-}
-
-/**
- * @deprecated Use `BedrockChat` instead.
- */
-export const ChatBedrock = BedrockChat;
+export * from "@langchain/community/chat_models/bedrock/web";
diff --git a/langchain/src/chat_models/cloudflare_workersai.ts b/langchain/src/chat_models/cloudflare_workersai.ts
index b8d2f5971814..009e5183f0a0 100644
--- a/langchain/src/chat_models/cloudflare_workersai.ts
+++ b/langchain/src/chat_models/cloudflare_workersai.ts
@@ -1,247 +1 @@
-import { SimpleChatModel, BaseChatModelParams } from "./base.js";
-import { BaseLanguageModelCallOptions } from "../base_language/index.js";
-import {
- AIMessageChunk,
- BaseMessage,
- ChatGenerationChunk,
- ChatMessage,
-} from "../schema/index.js";
-import { getEnvironmentVariable } from "../util/env.js";
-import { CloudflareWorkersAIInput } from "../llms/cloudflare_workersai.js";
-import { CallbackManagerForLLMRun } from "../callbacks/manager.js";
-import { convertEventStreamToIterableReadableDataStream } from "../util/event-source-parse.js";
-
-/**
- * An interface defining the options for a Cloudflare Workers AI call. It extends
- * the BaseLanguageModelCallOptions interface.
- */
-export interface ChatCloudflareWorkersAICallOptions
- extends BaseLanguageModelCallOptions {}
-
-/**
- * A class that enables calls to the Cloudflare Workers AI API to access large language
- * models in a chat-like fashion. It extends the SimpleChatModel class and
- * implements the CloudflareWorkersAIInput interface.
- * @example
- * ```typescript
- * const model = new ChatCloudflareWorkersAI({
- * model: "@cf/meta/llama-2-7b-chat-int8",
- * cloudflareAccountId: process.env.CLOUDFLARE_ACCOUNT_ID,
- * cloudflareApiToken: process.env.CLOUDFLARE_API_TOKEN
- * });
- *
- * const response = await model.invoke([
- * ["system", "You are a helpful assistant that translates English to German."],
- * ["human", `Translate "I love programming".`]
- * ]);
- *
- * console.log(response);
- * ```
- */
-export class ChatCloudflareWorkersAI
- extends SimpleChatModel
- implements CloudflareWorkersAIInput
-{
- static lc_name() {
- return "ChatCloudflareWorkersAI";
- }
-
- lc_serializable = true;
-
- model = "@cf/meta/llama-2-7b-chat-int8";
-
- cloudflareAccountId?: string;
-
- cloudflareApiToken?: string;
-
- baseUrl: string;
-
- streaming = false;
-
- constructor(fields?: CloudflareWorkersAIInput & BaseChatModelParams) {
- super(fields ?? {});
-
- this.model = fields?.model ?? this.model;
- this.streaming = fields?.streaming ?? this.streaming;
- this.cloudflareAccountId =
- fields?.cloudflareAccountId ??
- getEnvironmentVariable("CLOUDFLARE_ACCOUNT_ID");
- this.cloudflareApiToken =
- fields?.cloudflareApiToken ??
- getEnvironmentVariable("CLOUDFLARE_API_TOKEN");
- this.baseUrl =
- fields?.baseUrl ??
- `https://api.cloudflare.com/client/v4/accounts/${this.cloudflareAccountId}/ai/run`;
- if (this.baseUrl.endsWith("/")) {
- this.baseUrl = this.baseUrl.slice(0, -1);
- }
- }
-
- get lc_secrets(): { [key: string]: string } | undefined {
- return {
- cloudflareApiToken: "CLOUDFLARE_API_TOKEN",
- };
- }
-
- _llmType() {
- return "cloudflare";
- }
-
- /** Get the identifying parameters for this LLM. */
- get identifyingParams() {
- return { model: this.model };
- }
-
- /**
- * Get the parameters used to invoke the model
- */
- invocationParams(_options?: this["ParsedCallOptions"]) {
- return {
- model: this.model,
- };
- }
-
- _combineLLMOutput() {
- return {};
- }
-
- /**
- * Method to validate the environment.
- */
- validateEnvironment() {
- if (!this.cloudflareAccountId) {
- throw new Error(
- `No Cloudflare account ID found. Please provide it when instantiating the CloudflareWorkersAI class, or set it as "CLOUDFLARE_ACCOUNT_ID" in your environment variables.`
- );
- }
- if (!this.cloudflareApiToken) {
- throw new Error(
- `No Cloudflare API key found. Please provide it when instantiating the CloudflareWorkersAI class, or set it as "CLOUDFLARE_API_KEY" in your environment variables.`
- );
- }
- }
-
- async _request(
- messages: BaseMessage[],
- options: this["ParsedCallOptions"],
- stream?: boolean
- ) {
- this.validateEnvironment();
- const url = `${this.baseUrl}/${this.model}`;
- const headers = {
- Authorization: `Bearer ${this.cloudflareApiToken}`,
- "Content-Type": "application/json",
- };
-
- const formattedMessages = this._formatMessages(messages);
-
- const data = { messages: formattedMessages, stream };
- return this.caller.call(async () => {
- const response = await fetch(url, {
- method: "POST",
- headers,
- body: JSON.stringify(data),
- signal: options.signal,
- });
- if (!response.ok) {
- const error = new Error(
- `Cloudflare LLM call failed with status code ${response.status}`
- );
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- (error as any).response = response;
- throw error;
- }
- return response;
- });
- }
-
- async *_streamResponseChunks(
- messages: BaseMessage[],
- options: this["ParsedCallOptions"],
- runManager?: CallbackManagerForLLMRun
- ): AsyncGenerator {
- const response = await this._request(messages, options, true);
- if (!response.body) {
- throw new Error("Empty response from Cloudflare. Please try again.");
- }
- const stream = convertEventStreamToIterableReadableDataStream(
- response.body
- );
- for await (const chunk of stream) {
- if (chunk !== "[DONE]") {
- const parsedChunk = JSON.parse(chunk);
- const generationChunk = new ChatGenerationChunk({
- message: new AIMessageChunk({ content: parsedChunk.response }),
- text: parsedChunk.response,
- });
- yield generationChunk;
- // eslint-disable-next-line no-void
- void runManager?.handleLLMNewToken(generationChunk.text ?? "");
- }
- }
- }
-
- protected _formatMessages(
- messages: BaseMessage[]
- ): { role: string; content: string }[] {
- const formattedMessages = messages.map((message) => {
- let role;
- if (message._getType() === "human") {
- role = "user";
- } else if (message._getType() === "ai") {
- role = "assistant";
- } else if (message._getType() === "system") {
- role = "system";
- } else if (ChatMessage.isInstance(message)) {
- role = message.role;
- } else {
- console.warn(
- `Unsupported message type passed to Cloudflare: "${message._getType()}"`
- );
- role = "user";
- }
- if (typeof message.content !== "string") {
- throw new Error(
- "ChatCloudflareWorkersAI currently does not support non-string message content."
- );
- }
- return {
- role,
- content: message.content,
- };
- });
- return formattedMessages;
- }
-
- /** @ignore */
- async _call(
- messages: BaseMessage[],
- options: this["ParsedCallOptions"],
- runManager?: CallbackManagerForLLMRun
- ): Promise {
- if (!this.streaming) {
- const response = await this._request(messages, options);
-
- const responseData = await response.json();
-
- return responseData.result.response;
- } else {
- const stream = this._streamResponseChunks(messages, options, runManager);
- let finalResult: ChatGenerationChunk | undefined;
- for await (const chunk of stream) {
- if (finalResult === undefined) {
- finalResult = chunk;
- } else {
- finalResult = finalResult.concat(chunk);
- }
- }
- const messageContent = finalResult?.message.content;
- if (messageContent && typeof messageContent !== "string") {
- throw new Error(
- "Non-string output for ChatCloudflareWorkersAI is currently not supported."
- );
- }
- return messageContent ?? "";
- }
- }
-}
+export * from "@langchain/community/chat_models/cloudflare_workersai";
diff --git a/langchain/src/chat_models/fireworks.ts b/langchain/src/chat_models/fireworks.ts
index 29e12cc34ea2..438f96c7c33d 100644
--- a/langchain/src/chat_models/fireworks.ts
+++ b/langchain/src/chat_models/fireworks.ts
@@ -1,137 +1 @@
-import type { OpenAI as OpenAIClient } from "openai";
-import type { ChatOpenAICallOptions, OpenAIChatInput } from "./openai.js";
-import type { OpenAICoreRequestOptions } from "../types/openai-types.js";
-import type { BaseChatModelParams } from "./base.js";
-import { ChatOpenAI } from "./openai.js";
-import { getEnvironmentVariable } from "../util/env.js";
-
-type FireworksUnsupportedArgs =
- | "frequencyPenalty"
- | "presencePenalty"
- | "logitBias"
- | "functions";
-
-type FireworksUnsupportedCallOptions = "functions" | "function_call" | "tools";
-
-export type ChatFireworksCallOptions = Partial<
- Omit
->;
-
-/**
- * Wrapper around Fireworks API for large language models fine-tuned for chat
- *
- * 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
- * ```typescript
- * const model = new ChatFireworks({
- * temperature: 0.9,
- * fireworksApiKey: "YOUR-API-KEY",
- * });
- *
- * const response = await model.invoke("Hello, how are you?");
- * console.log(response);
- * ```
- */
-export class ChatFireworks extends ChatOpenAI {
- static lc_name() {
- return "ChatFireworks";
- }
-
- _llmType() {
- return "fireworks";
- }
-
- get lc_secrets(): { [key: string]: string } | undefined {
- return {
- fireworksApiKey: "FIREWORKS_API_KEY",
- };
- }
-
- lc_serializable = true;
-
- fireworksApiKey?: string;
-
- constructor(
- fields?: Partial<
- Omit
- > &
- BaseChatModelParams & { fireworksApiKey?: string }
- ) {
- const fireworksApiKey =
- fields?.fireworksApiKey || getEnvironmentVariable("FIREWORKS_API_KEY");
-
- if (!fireworksApiKey) {
- throw new Error(
- `Fireworks API key not found. Please set the FIREWORKS_API_KEY environment variable or provide the key into "fireworksApiKey"`
- );
- }
-
- super({
- ...fields,
- modelName:
- fields?.modelName || "accounts/fireworks/models/llama-v2-13b-chat",
- openAIApiKey: fireworksApiKey,
- configuration: {
- baseURL: "https://api.fireworks.ai/inference/v1",
- },
- });
-
- this.fireworksApiKey = fireworksApiKey;
- }
-
- toJSON() {
- const result = super.toJSON();
-
- if (
- "kwargs" in result &&
- typeof result.kwargs === "object" &&
- result.kwargs != null
- ) {
- delete result.kwargs.openai_api_key;
- delete result.kwargs.configuration;
- }
-
- return result;
- }
-
- async completionWithRetry(
- request: OpenAIClient.Chat.ChatCompletionCreateParamsStreaming,
- options?: OpenAICoreRequestOptions
- ): Promise>;
-
- async completionWithRetry(
- request: OpenAIClient.Chat.ChatCompletionCreateParamsNonStreaming,
- options?: OpenAICoreRequestOptions
- ): Promise;
-
- /**
- * Calls the Fireworks API with retry logic in case of failures.
- * @param request The request to send to the Fireworks API.
- * @param options Optional configuration for the API call.
- * @returns The response from the Fireworks API.
- */
- async completionWithRetry(
- request:
- | OpenAIClient.Chat.ChatCompletionCreateParamsStreaming
- | OpenAIClient.Chat.ChatCompletionCreateParamsNonStreaming,
- options?: OpenAICoreRequestOptions
- ): Promise<
- | AsyncIterable
- | OpenAIClient.Chat.Completions.ChatCompletion
- > {
- delete request.frequency_penalty;
- delete request.presence_penalty;
- delete request.logit_bias;
- delete request.functions;
-
- if (request.stream === true) {
- return super.completionWithRetry(request, options);
- }
-
- return super.completionWithRetry(request, options);
- }
-}
+export * from "@langchain/community/chat_models/fireworks";
diff --git a/langchain/src/chat_models/googlepalm.ts b/langchain/src/chat_models/googlepalm.ts
index 56cca1023943..53f338a9674d 100644
--- a/langchain/src/chat_models/googlepalm.ts
+++ b/langchain/src/chat_models/googlepalm.ts
@@ -1,340 +1 @@
-import { DiscussServiceClient } from "@google-ai/generativelanguage";
-import type { protos } from "@google-ai/generativelanguage";
-import { GoogleAuth } from "google-auth-library";
-import { CallbackManagerForLLMRun } from "../callbacks/manager.js";
-import {
- AIMessage,
- BaseMessage,
- ChatMessage,
- ChatResult,
- isBaseMessage,
-} from "../schema/index.js";
-import { getEnvironmentVariable } from "../util/env.js";
-import { BaseChatModel, BaseChatModelParams } from "./base.js";
-
-export type BaseMessageExamplePair = {
- input: BaseMessage;
- output: BaseMessage;
-};
-
-/**
- * An interface defining the input to the ChatGooglePaLM class.
- */
-export interface GooglePaLMChatInput extends BaseChatModelParams {
- /**
- * Model Name to use
- *
- * Note: The format must follow the pattern - `models/{model}`
- */
- modelName?: string;
-
- /**
- * Controls the randomness of the output.
- *
- * Values can range from [0.0,1.0], inclusive. A value closer to 1.0
- * will produce responses that are more varied and creative, while
- * a value closer to 0.0 will typically result in less surprising
- * responses from the model.
- *
- * Note: The default value varies by model
- */
- temperature?: number;
-
- /**
- * Top-p changes how the model selects tokens for output.
- *
- * Tokens are selected from most probable to least until the sum
- * of their probabilities equals the top-p value.
- *
- * For example, if tokens A, B, and C have a probability of
- * .3, .2, and .1 and the top-p value is .5, then the model will
- * select either A or B as the next token (using temperature).
- *
- * Note: The default value varies by model
- */
- topP?: number;
-
- /**
- * Top-k changes how the model selects tokens for output.
- *
- * A top-k of 1 means the selected token is the most probable among
- * all tokens in the model’s vocabulary (also called greedy decoding),
- * while a top-k of 3 means that the next token is selected from
- * among the 3 most probable tokens (using temperature).
- *
- * Note: The default value varies by model
- */
- topK?: number;
-
- examples?:
- | protos.google.ai.generativelanguage.v1beta2.IExample[]
- | BaseMessageExamplePair[];
-
- /**
- * Google Palm API key to use
- */
- apiKey?: string;
-}
-
-function getMessageAuthor(message: BaseMessage) {
- const type = message._getType();
- if (ChatMessage.isInstance(message)) {
- return message.role;
- }
- return message.name ?? type;
-}
-
-/**
- * A class that wraps the Google Palm chat model.
- * @example
- * ```typescript
- * const model = new ChatGooglePaLM({
- * apiKey: "",
- * temperature: 0.7,
- * modelName: "models/chat-bison-001",
- * topK: 40,
- * topP: 1,
- * examples: [
- * {
- * input: new HumanMessage("What is your favorite sock color?"),
- * output: new AIMessage("My favorite sock color be arrrr-ange!"),
- * },
- * ],
- * });
- * const questions = [
- * new SystemMessage(
- * "You are a funny assistant that answers in pirate language."
- * ),
- * new HumanMessage("What is your favorite food?"),
- * ];
- * const res = await model.call(questions);
- * console.log({ res });
- * ```
- */
-export class ChatGooglePaLM
- extends BaseChatModel
- implements GooglePaLMChatInput
-{
- static lc_name() {
- return "ChatGooglePaLM";
- }
-
- lc_serializable = true;
-
- get lc_secrets(): { [key: string]: string } | undefined {
- return {
- apiKey: "GOOGLE_PALM_API_KEY",
- };
- }
-
- modelName = "models/chat-bison-001";
-
- temperature?: number; // default value chosen based on model
-
- topP?: number; // default value chosen based on model
-
- topK?: number; // default value chosen based on model
-
- examples: protos.google.ai.generativelanguage.v1beta2.IExample[] = [];
-
- apiKey?: string;
-
- private client: DiscussServiceClient;
-
- constructor(fields?: GooglePaLMChatInput) {
- super(fields ?? {});
-
- this.modelName = fields?.modelName ?? this.modelName;
-
- this.temperature = fields?.temperature ?? this.temperature;
- if (this.temperature && (this.temperature < 0 || this.temperature > 1)) {
- throw new Error("`temperature` must be in the range of [0.0,1.0]");
- }
-
- this.topP = fields?.topP ?? this.topP;
- if (this.topP && this.topP < 0) {
- throw new Error("`topP` must be a positive integer");
- }
-
- this.topK = fields?.topK ?? this.topK;
- if (this.topK && this.topK < 0) {
- throw new Error("`topK` must be a positive integer");
- }
-
- this.examples =
- fields?.examples?.map((example) => {
- if (
- (isBaseMessage(example.input) &&
- typeof example.input.content !== "string") ||
- (isBaseMessage(example.output) &&
- typeof example.output.content !== "string")
- ) {
- throw new Error(
- "GooglePaLM example messages may only have string content."
- );
- }
- return {
- input: {
- ...example.input,
- content: example.input?.content as string,
- },
- output: {
- ...example.output,
- content: example.output?.content as string,
- },
- };
- }) ?? this.examples;
-
- this.apiKey =
- fields?.apiKey ?? getEnvironmentVariable("GOOGLE_PALM_API_KEY");
- if (!this.apiKey) {
- throw new Error(
- "Please set an API key for Google Palm 2 in the environment variable GOOGLE_PALM_API_KEY or in the `apiKey` field of the GooglePalm constructor"
- );
- }
-
- this.client = new DiscussServiceClient({
- authClient: new GoogleAuth().fromAPIKey(this.apiKey),
- });
- }
-
- _combineLLMOutput() {
- return [];
- }
-
- _llmType() {
- return "googlepalm";
- }
-
- async _generate(
- messages: BaseMessage[],
- options: this["ParsedCallOptions"],
- runManager?: CallbackManagerForLLMRun
- ): Promise {
- const palmMessages = await this.caller.callWithOptions(
- { signal: options.signal },
- this._generateMessage.bind(this),
- this._mapBaseMessagesToPalmMessages(messages),
- this._getPalmContextInstruction(messages),
- this.examples
- );
- const chatResult = this._mapPalmMessagesToChatResult(palmMessages);
-
- // Google Palm doesn't provide streaming as of now. But to support streaming handlers
- // we call the handler with entire response text
- void runManager?.handleLLMNewToken(
- chatResult.generations.length > 0 ? chatResult.generations[0].text : ""
- );
-
- return chatResult;
- }
-
- protected async _generateMessage(
- messages: protos.google.ai.generativelanguage.v1beta2.IMessage[],
- context?: string,
- examples?: protos.google.ai.generativelanguage.v1beta2.IExample[]
- ): Promise {
- const [palmMessages] = await this.client.generateMessage({
- candidateCount: 1,
- model: this.modelName,
- temperature: this.temperature,
- topK: this.topK,
- topP: this.topP,
- prompt: {
- context,
- examples,
- messages,
- },
- });
- return palmMessages;
- }
-
- protected _getPalmContextInstruction(
- messages: BaseMessage[]
- ): string | undefined {
- // get the first message and checks if it's a system 'system' messages
- const systemMessage =
- messages.length > 0 && getMessageAuthor(messages[0]) === "system"
- ? messages[0]
- : undefined;
- if (
- systemMessage?.content !== undefined &&
- typeof systemMessage.content !== "string"
- ) {
- throw new Error("Non-string system message content is not supported.");
- }
- return systemMessage?.content;
- }
-
- protected _mapBaseMessagesToPalmMessages(
- messages: BaseMessage[]
- ): protos.google.ai.generativelanguage.v1beta2.IMessage[] {
- // remove all 'system' messages
- const nonSystemMessages = messages.filter(
- (m) => getMessageAuthor(m) !== "system"
- );
-
- // requires alternate human & ai messages. Throw error if two messages are consecutive
- nonSystemMessages.forEach((msg, index) => {
- if (index < 1) return;
- if (
- getMessageAuthor(msg) === getMessageAuthor(nonSystemMessages[index - 1])
- ) {
- throw new Error(
- `Google PaLM requires alternate messages between authors`
- );
- }
- });
-
- return nonSystemMessages.map((m) => {
- if (typeof m.content !== "string") {
- throw new Error(
- "ChatGooglePaLM does not support non-string message content."
- );
- }
- return {
- author: getMessageAuthor(m),
- content: m.content,
- citationMetadata: {
- citationSources: m.additional_kwargs.citationSources as
- | protos.google.ai.generativelanguage.v1beta2.ICitationSource[]
- | undefined,
- },
- };
- });
- }
-
- protected _mapPalmMessagesToChatResult(
- msgRes: protos.google.ai.generativelanguage.v1beta2.IGenerateMessageResponse
- ): ChatResult {
- if (
- msgRes.candidates &&
- msgRes.candidates.length > 0 &&
- msgRes.candidates[0]
- ) {
- const message = msgRes.candidates[0];
- return {
- generations: [
- {
- text: message.content ?? "",
- message: new AIMessage({
- content: message.content ?? "",
- name: message.author === null ? undefined : message.author,
- additional_kwargs: {
- citationSources: message.citationMetadata?.citationSources,
- filters: msgRes.filters, // content filters applied
- },
- }),
- },
- ],
- };
- }
- // if rejected or error, return empty generations with reason in filters
- return {
- generations: [],
- llmOutput: {
- filters: msgRes.filters,
- },
- };
- }
-}
+export * from "@langchain/community/chat_models/googlepalm";
diff --git a/langchain/src/chat_models/googlevertexai/index.ts b/langchain/src/chat_models/googlevertexai/index.ts
index e8a3a07da320..b2977f65c20a 100644
--- a/langchain/src/chat_models/googlevertexai/index.ts
+++ b/langchain/src/chat_models/googlevertexai/index.ts
@@ -1,64 +1 @@
-import { GoogleAuthOptions } from "google-auth-library";
-import { BaseChatGoogleVertexAI, GoogleVertexAIChatInput } from "./common.js";
-import { GoogleVertexAILLMConnection } from "../../util/googlevertexai-connection.js";
-import { GAuthClient } from "../../util/googlevertexai-gauth.js";
-
-/**
- * Enables calls to the Google Cloud's Vertex AI API to access
- * Large Language Models in a chat-like fashion.
- *
- * To use, you will need to have one of the following authentication
- * methods in place:
- * - You are logged into an account permitted to the Google Cloud project
- * using Vertex AI.
- * - You are running this on a machine using a service account permitted to
- * the Google Cloud project using Vertex AI.
- * - The `GOOGLE_APPLICATION_CREDENTIALS` environment variable is set to the
- * path of a credentials file for a service account permitted to the
- * Google Cloud project using Vertex AI.
- * @example
- * ```typescript
- * const model = new ChatGoogleVertexAI({
- * temperature: 0.7,
- * });
- * const result = await model.invoke("What is the capital of France?");
- * ```
- */
-export class ChatGoogleVertexAI extends BaseChatGoogleVertexAI {
- static lc_name() {
- return "ChatVertexAI";
- }
-
- constructor(fields?: GoogleVertexAIChatInput) {
- super(fields);
-
- const client = new GAuthClient({
- scopes: "https://www.googleapis.com/auth/cloud-platform",
- ...fields?.authOptions,
- });
-
- this.connection = new GoogleVertexAILLMConnection(
- { ...fields, ...this },
- this.caller,
- client,
- false
- );
-
- this.streamedConnection = new GoogleVertexAILLMConnection(
- { ...fields, ...this },
- this.caller,
- client,
- true
- );
- }
-}
-
-export type {
- ChatExample,
- GoogleVertexAIChatAuthor,
- GoogleVertexAIChatInput,
- GoogleVertexAIChatInstance,
- GoogleVertexAIChatMessage,
- GoogleVertexAIChatMessageFields,
- GoogleVertexAIChatPrediction,
-} from "./common.js";
+export * from "@langchain/community/chat_models/googlevertexai";
diff --git a/langchain/src/chat_models/googlevertexai/web.ts b/langchain/src/chat_models/googlevertexai/web.ts
index acbaa9144f4c..4c350a89266a 100644
--- a/langchain/src/chat_models/googlevertexai/web.ts
+++ b/langchain/src/chat_models/googlevertexai/web.ts
@@ -1,66 +1 @@
-import { GoogleVertexAILLMConnection } from "../../util/googlevertexai-connection.js";
-import {
- WebGoogleAuthOptions,
- WebGoogleAuth,
-} from "../../util/googlevertexai-webauth.js";
-import { BaseChatGoogleVertexAI, GoogleVertexAIChatInput } from "./common.js";
-
-/**
- * Enables calls to the Google Cloud's Vertex AI API to access
- * Large Language Models in a chat-like fashion.
- *
- * This entrypoint and class are intended to be used in web environments like Edge
- * functions where you do not have access to the file system. It supports passing
- * service account credentials directly as a "GOOGLE_VERTEX_AI_WEB_CREDENTIALS"
- * environment variable or directly as "authOptions.credentials".
- * @example
- * ```typescript
- * const model = new ChatGoogleVertexAI({
- * temperature: 0.7,
- * });
- * const result = await model.invoke(
- * "How do I implement a binary search algorithm in Python?",
- * );
- * ```
- */
-export class ChatGoogleVertexAI extends BaseChatGoogleVertexAI {
- static lc_name() {
- return "ChatVertexAI";
- }
-
- get lc_secrets(): { [key: string]: string } {
- return {
- "authOptions.credentials": "GOOGLE_VERTEX_AI_WEB_CREDENTIALS",
- };
- }
-
- constructor(fields?: GoogleVertexAIChatInput) {
- super(fields);
-
- const client = new WebGoogleAuth(fields?.authOptions);
-
- this.connection = new GoogleVertexAILLMConnection(
- { ...fields, ...this },
- this.caller,
- client,
- false
- );
-
- this.streamedConnection = new GoogleVertexAILLMConnection(
- { ...fields, ...this },
- this.caller,
- client,
- true
- );
- }
-}
-
-export type {
- ChatExample,
- GoogleVertexAIChatAuthor,
- GoogleVertexAIChatInput,
- GoogleVertexAIChatInstance,
- GoogleVertexAIChatMessage,
- GoogleVertexAIChatMessageFields,
- GoogleVertexAIChatPrediction,
-} from "./common.js";
+export * from "@langchain/community/chat_models/googlevertexai/web";
diff --git a/langchain/src/chat_models/iflytek_xinghuo/index.ts b/langchain/src/chat_models/iflytek_xinghuo/index.ts
index ac54461be18a..9b988a537704 100644
--- a/langchain/src/chat_models/iflytek_xinghuo/index.ts
+++ b/langchain/src/chat_models/iflytek_xinghuo/index.ts
@@ -1,43 +1 @@
-import WebSocket from "ws";
-import { BaseChatIflytekXinghuo } from "./common.js";
-import {
- BaseWebSocketStream,
- WebSocketStreamOptions,
-} from "../../util/iflytek_websocket_stream.js";
-
-class WebSocketStream extends BaseWebSocketStream {
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- openWebSocket(url: string, options: WebSocketStreamOptions): WebSocket {
- return new WebSocket(url, options.protocols ?? []);
- }
-}
-
-/**
- * @example
- * ```typescript
- * const model = new ChatIflytekXinghuo();
- * const response = await model.call([new HumanMessage("Nice to meet you!")]);
- * console.log(response);
- * ```
- */
-export class ChatIflytekXinghuo extends BaseChatIflytekXinghuo {
- async openWebSocketStream(
- options: WebSocketStreamOptions
- ): Promise {
- const host = "spark-api.xf-yun.com";
- const date = new Date().toUTCString();
- const url = `GET /${this.version}/chat HTTP/1.1`;
- const { createHmac } = await import("node:crypto");
- const hash = createHmac("sha256", this.iflytekApiSecret)
- .update(`host: ${host}\ndate: ${date}\n${url}`)
- .digest("base64");
- const authorization_origin = `api_key="${this.iflytekApiKey}", algorithm="hmac-sha256", headers="host date request-line", signature="${hash}"`;
- const authorization = Buffer.from(authorization_origin).toString("base64");
- let authWebSocketUrl = this.apiUrl;
- authWebSocketUrl += `?authorization=${authorization}`;
- authWebSocketUrl += `&host=${encodeURIComponent(host)}`;
- authWebSocketUrl += `&date=${encodeURIComponent(date)}`;
- return new WebSocketStream(authWebSocketUrl, options) as WebSocketStream;
- }
-}
+export * from "@langchain/community/chat_models/iflytek_xinghuo";
diff --git a/langchain/src/chat_models/iflytek_xinghuo/web.ts b/langchain/src/chat_models/iflytek_xinghuo/web.ts
index 87b372b802ad..8867445ee59c 100644
--- a/langchain/src/chat_models/iflytek_xinghuo/web.ts
+++ b/langchain/src/chat_models/iflytek_xinghuo/web.ts
@@ -1,49 +1 @@
-import { BaseChatIflytekXinghuo } from "./common.js";
-import {
- WebSocketStreamOptions,
- BaseWebSocketStream,
-} from "../../util/iflytek_websocket_stream.js";
-
-class WebSocketStream extends BaseWebSocketStream {
- openWebSocket(url: string, options: WebSocketStreamOptions): WebSocket {
- return new WebSocket(url, options.protocols ?? []);
- }
-}
-
-/**
- * @example
- * ```typescript
- * const model = new ChatIflytekXinghuo();
- * const response = await model.call([new HumanMessage("Nice to meet you!")]);
- * console.log(response);
- * ```
- */
-export class ChatIflytekXinghuo extends BaseChatIflytekXinghuo {
- async openWebSocketStream(
- options: WebSocketStreamOptions
- ): Promise {
- const host = "spark-api.xf-yun.com";
- const date = new Date().toUTCString();
- const url = `GET /${this.version}/chat HTTP/1.1`;
- const keyBuffer = new TextEncoder().encode(this.iflytekApiSecret);
- const dataBuffer = new TextEncoder().encode(
- `host: ${host}\ndate: ${date}\n${url}`
- );
- const cryptoKey = await crypto.subtle.importKey(
- "raw",
- keyBuffer,
- { name: "HMAC", hash: "SHA-256" },
- false,
- ["sign"]
- );
- const signature = await crypto.subtle.sign("HMAC", cryptoKey, dataBuffer);
- const hash = window.btoa(String.fromCharCode(...new Uint8Array(signature)));
- const authorization_origin = `api_key="${this.iflytekApiKey}", algorithm="hmac-sha256", headers="host date request-line", signature="${hash}"`;
- const authorization = window.btoa(authorization_origin);
- let authWebSocketUrl = this.apiUrl;
- authWebSocketUrl += `?authorization=${authorization}`;
- authWebSocketUrl += `&host=${encodeURIComponent(host)}`;
- authWebSocketUrl += `&date=${encodeURIComponent(date)}`;
- return new WebSocketStream(authWebSocketUrl, options) as WebSocketStream;
- }
-}
+export * from "@langchain/community/chat_models/iflytek_xinghuo/web";
diff --git a/langchain/src/chat_models/llama_cpp.ts b/langchain/src/chat_models/llama_cpp.ts
index 3df8b0d2a3c9..ae06e6116cfc 100644
--- a/langchain/src/chat_models/llama_cpp.ts
+++ b/langchain/src/chat_models/llama_cpp.ts
@@ -1,322 +1 @@
-import {
- LlamaModel,
- LlamaContext,
- LlamaChatSession,
- type ConversationInteraction,
-} from "node-llama-cpp";
-import { SimpleChatModel, BaseChatModelParams } from "./base.js";
-import {
- LlamaBaseCppInputs,
- createLlamaModel,
- createLlamaContext,
-} from "../util/llama_cpp.js";
-import { BaseLanguageModelCallOptions } from "../base_language/index.js";
-import { CallbackManagerForLLMRun } from "../callbacks/manager.js";
-import {
- BaseMessage,
- ChatGenerationChunk,
- AIMessageChunk,
- ChatMessage,
-} from "../schema/index.js";
-
-/**
- * Note that the modelPath is the only required parameter. For testing you
- * can set this in the environment variable `LLAMA_PATH`.
- */
-export interface LlamaCppInputs
- extends LlamaBaseCppInputs,
- BaseChatModelParams {}
-
-export interface LlamaCppCallOptions extends BaseLanguageModelCallOptions {
- /** The maximum number of tokens the response should contain. */
- maxTokens?: number;
- /** A function called when matching the provided token array */
- onToken?: (tokens: number[]) => void;
-}
-
-/**
- * To use this model you need to have the `node-llama-cpp` module installed.
- * This can be installed using `npm install -S node-llama-cpp` and the minimum
- * version supported in version 2.0.0.
- * This also requires that have a locally built version of Llama2 installed.
- * @example
- * ```typescript
- * // Initialize the ChatLlamaCpp model with the path to the model binary file.
- * const model = new ChatLlamaCpp({
- * modelPath: "/Replace/with/path/to/your/model/gguf-llama2-q4_0.bin",
- * temperature: 0.5,
- * });
- *
- * // Call the model with a message and await the response.
- * const response = await model.call([
- * new HumanMessage({ content: "My name is John." }),
- * ]);
- *
- * // Log the response to the console.
- * console.log({ response });
- *
- * ```
- */
-export class ChatLlamaCpp extends SimpleChatModel {
- declare CallOptions: LlamaCppCallOptions;
-
- static inputs: LlamaCppInputs;
-
- maxTokens?: number;
-
- temperature?: number;
-
- topK?: number;
-
- topP?: number;
-
- trimWhitespaceSuffix?: boolean;
-
- _model: LlamaModel;
-
- _context: LlamaContext;
-
- _session: LlamaChatSession | null;
-
- static lc_name() {
- return "ChatLlamaCpp";
- }
-
- constructor(inputs: LlamaCppInputs) {
- super(inputs);
- this.maxTokens = inputs?.maxTokens;
- this.temperature = inputs?.temperature;
- this.topK = inputs?.topK;
- this.topP = inputs?.topP;
- this.trimWhitespaceSuffix = inputs?.trimWhitespaceSuffix;
- this._model = createLlamaModel(inputs);
- this._context = createLlamaContext(this._model, inputs);
- this._session = null;
- }
-
- _llmType() {
- return "llama2_cpp";
- }
-
- /** @ignore */
- _combineLLMOutput() {
- return {};
- }
-
- invocationParams() {
- return {
- maxTokens: this.maxTokens,
- temperature: this.temperature,
- topK: this.topK,
- topP: this.topP,
- trimWhitespaceSuffix: this.trimWhitespaceSuffix,
- };
- }
-
- /** @ignore */
- async _call(
- messages: BaseMessage[],
- options: this["ParsedCallOptions"]
- ): Promise {
- let prompt = "";
-
- if (messages.length > 1) {
- // We need to build a new _session
- prompt = this._buildSession(messages);
- } else if (!this._session) {
- prompt = this._buildSession(messages);
- } else {
- if (typeof messages[0].content !== "string") {
- throw new Error(
- "ChatLlamaCpp does not support non-string message content in sessions."
- );
- }
- // If we already have a session then we should just have a single prompt
- prompt = messages[0].content;
- }
-
- try {
- const promptOptions = {
- onToken: options.onToken,
- maxTokens: this?.maxTokens,
- temperature: this?.temperature,
- topK: this?.topK,
- topP: this?.topP,
- trimWhitespaceSuffix: this?.trimWhitespaceSuffix,
- };
- // @ts-expect-error - TS2531: Object is possibly 'null'.
- const completion = await this._session.prompt(prompt, promptOptions);
- return completion;
- } catch (e) {
- throw new Error("Error getting prompt completion.");
- }
- }
-
- async *_streamResponseChunks(
- input: BaseMessage[],
- _options: this["ParsedCallOptions"],
- runManager?: CallbackManagerForLLMRun
- ): AsyncGenerator {
- const promptOptions = {
- temperature: this?.temperature,
- topK: this?.topK,
- topP: this?.topP,
- };
-
- const prompt = this._buildPrompt(input);
-
- const stream = await this.caller.call(async () =>
- this._context.evaluate(this._context.encode(prompt), promptOptions)
- );
-
- for await (const chunk of stream) {
- yield new ChatGenerationChunk({
- text: this._context.decode([chunk]),
- message: new AIMessageChunk({
- content: this._context.decode([chunk]),
- }),
- generationInfo: {},
- });
- await runManager?.handleLLMNewToken(this._context.decode([chunk]) ?? "");
- }
- }
-
- // This constructs a new session if we need to adding in any sys messages or previous chats
- protected _buildSession(messages: BaseMessage[]): string {
- let prompt = "";
- let sysMessage = "";
- let noSystemMessages: BaseMessage[] = [];
- let interactions: ConversationInteraction[] = [];
-
- // Let's see if we have a system message
- if (messages.findIndex((msg) => msg._getType() === "system") !== -1) {
- const sysMessages = messages.filter(
- (message) => message._getType() === "system"
- );
-
- const systemMessageContent = sysMessages[sysMessages.length - 1].content;
-
- if (typeof systemMessageContent !== "string") {
- throw new Error(
- "ChatLlamaCpp does not support non-string message content in sessions."
- );
- }
- // Only use the last provided system message
- sysMessage = systemMessageContent;
-
- // Now filter out the system messages
- noSystemMessages = messages.filter(
- (message) => message._getType() !== "system"
- );
- } else {
- noSystemMessages = messages;
- }
-
- // Lets see if we just have a prompt left or are their previous interactions?
- if (noSystemMessages.length > 1) {
- // Is the last message a prompt?
- if (
- noSystemMessages[noSystemMessages.length - 1]._getType() === "human"
- ) {
- const finalMessageContent =
- noSystemMessages[noSystemMessages.length - 1].content;
- if (typeof finalMessageContent !== "string") {
- throw new Error(
- "ChatLlamaCpp does not support non-string message content in sessions."
- );
- }
- prompt = finalMessageContent;
- interactions = this._convertMessagesToInteractions(
- noSystemMessages.slice(0, noSystemMessages.length - 1)
- );
- } else {
- interactions = this._convertMessagesToInteractions(noSystemMessages);
- }
- } else {
- if (typeof noSystemMessages[0].content !== "string") {
- throw new Error(
- "ChatLlamaCpp does not support non-string message content in sessions."
- );
- }
- // If there was only a single message we assume it's a prompt
- prompt = noSystemMessages[0].content;
- }
-
- // Now lets construct a session according to what we got
- if (sysMessage !== "" && interactions.length > 0) {
- this._session = new LlamaChatSession({
- context: this._context,
- conversationHistory: interactions,
- systemPrompt: sysMessage,
- });
- } else if (sysMessage !== "" && interactions.length === 0) {
- this._session = new LlamaChatSession({
- context: this._context,
- systemPrompt: sysMessage,
- });
- } else if (sysMessage === "" && interactions.length > 0) {
- this._session = new LlamaChatSession({
- context: this._context,
- conversationHistory: interactions,
- });
- } else {
- this._session = new LlamaChatSession({
- context: this._context,
- });
- }
-
- return prompt;
- }
-
- // This builds a an array of interactions
- protected _convertMessagesToInteractions(
- messages: BaseMessage[]
- ): ConversationInteraction[] {
- const result: ConversationInteraction[] = [];
-
- for (let i = 0; i < messages.length; i += 2) {
- if (i + 1 < messages.length) {
- const prompt = messages[i].content;
- const response = messages[i + 1].content;
- if (typeof prompt !== "string" || typeof response !== "string") {
- throw new Error(
- "ChatLlamaCpp does not support non-string message content."
- );
- }
- result.push({
- prompt,
- response,
- });
- }
- }
-
- return result;
- }
-
- protected _buildPrompt(input: BaseMessage[]): string {
- const prompt = input
- .map((message) => {
- let messageText;
- if (message._getType() === "human") {
- messageText = `[INST] ${message.content} [/INST]`;
- } else if (message._getType() === "ai") {
- messageText = message.content;
- } else if (message._getType() === "system") {
- messageText = `<> ${message.content} <>`;
- } else if (ChatMessage.isInstance(message)) {
- messageText = `\n\n${message.role[0].toUpperCase()}${message.role.slice(
- 1
- )}: ${message.content}`;
- } else {
- console.warn(
- `Unsupported message type passed to llama_cpp: "${message._getType()}"`
- );
- messageText = "";
- }
- return messageText;
- })
- .join("\n");
-
- return prompt;
- }
-}
+export * from "@langchain/community/chat_models/llama_cpp";
diff --git a/langchain/src/chat_models/minimax.ts b/langchain/src/chat_models/minimax.ts
index c0e521d6fec0..6cb2a1436dbd 100644
--- a/langchain/src/chat_models/minimax.ts
+++ b/langchain/src/chat_models/minimax.ts
@@ -1,880 +1 @@
-import type { OpenAI as OpenAIClient } from "openai";
-
-import { BaseChatModel, BaseChatModelParams } from "./base.js";
-import {
- AIMessage,
- BaseMessage,
- ChatGeneration,
- ChatMessage,
- ChatResult,
- HumanMessage,
-} from "../schema/index.js";
-import { CallbackManagerForLLMRun } from "../callbacks/manager.js";
-import { getEnvironmentVariable } from "../util/env.js";
-import { StructuredTool } from "../tools/index.js";
-import { BaseFunctionCallOptions } from "../base_language/index.js";
-import { formatToOpenAIFunction } from "../tools/convert_to_openai.js";
-
-/**
- * Type representing the sender_type of a message in the Minimax chat model.
- */
-export type MinimaxMessageRole = "BOT" | "USER" | "FUNCTION";
-
-/**
- * Interface representing a message in the Minimax chat model.
- */
-interface MinimaxChatCompletionRequestMessage {
- sender_type: MinimaxMessageRole;
- sender_name?: string;
- text: string;
-}
-
-/**
- * Interface representing a request for a chat completion.
- */
-interface MinimaxChatCompletionRequest {
- model: string;
- messages: MinimaxChatCompletionRequestMessage[];
- stream?: boolean;
- prompt?: string;
- temperature?: number;
- top_p?: number;
- tokens_to_generate?: number;
- skip_info_mask?: boolean;
- mask_sensitive_info?: boolean;
- beam_width?: number;
- use_standard_sse?: boolean;
- role_meta?: RoleMeta;
- bot_setting?: BotSetting[];
- reply_constraints?: ReplyConstraints;
- sample_messages?: MinimaxChatCompletionRequestMessage[];
- /**
- * A list of functions the model may generate JSON inputs for.
- * @type {Array}
- */
- functions?: OpenAIClient.Chat.ChatCompletionCreateParams.Function[];
- plugins?: string[];
-}
-
-interface RoleMeta {
- role_meta: string;
- bot_name: string;
-}
-
-interface RawGlyph {
- type: "raw";
- raw_glyph: string;
-}
-
-interface JsonGlyph {
- type: "json_value";
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- json_properties: any;
-}
-
-type ReplyConstraintsGlyph = RawGlyph | JsonGlyph;
-
-interface ReplyConstraints {
- sender_type: string;
- sender_name: string;
- glyph?: ReplyConstraintsGlyph;
-}
-
-interface BotSetting {
- content: string;
- bot_name: string;
-}
-
-export declare interface ConfigurationParameters {
- basePath?: string;
- headers?: Record;
-}
-
-/**
- * Interface defining the input to the ChatMinimax class.
- */
-declare interface MinimaxChatInputBase {
- /** Model name to use
- * @default "abab5.5-chat"
- */
- modelName: string;
-
- /** Whether to stream the results or not. Defaults to false. */
- streaming?: boolean;
-
- prefixMessages?: MinimaxChatCompletionRequestMessage[];
-
- /**
- * API key to use when making requests. Defaults to the value of
- * `MINIMAX_GROUP_ID` environment variable.
- */
- minimaxGroupId?: string;
-
- /**
- * Secret key to use when making requests. Defaults to the value of
- * `MINIMAX_API_KEY` environment variable.
- */
- minimaxApiKey?: string;
-
- /** Amount of randomness injected into the response. Ranges
- * from 0 to 1 (0 is not included). Use temp closer to 0 for analytical /
- * multiple choice, and temp closer to 1 for creative
- * and generative tasks. Defaults to 0.95.
- */
- temperature?: number;
-
- /**
- * The smaller the sampling method, the more determinate the result;
- * the larger the number, the more random the result.
- */
- topP?: number;
-
- /**
- * Enable Chatcompletion pro
- */
- proVersion?: boolean;
-
- /**
- * Pay attention to the maximum number of tokens generated,
- * this parameter does not affect the generation effect of the model itself,
- * but only realizes the function by truncating the tokens exceeding the limit.
- * It is necessary to ensure that the number of tokens of the input context plus this value is less than 6144 or 16384,
- * otherwise the request will fail.
- */
- tokensToGenerate?: number;
-}
-
-declare interface MinimaxChatInputNormal {
- /**
- * Dialogue setting, characters, or functionality setting.
- */
- prompt?: string;
- /**
- * Sensitize text information in the output that may involve privacy issues,
- * currently including but not limited to emails, domain names,
- * links, ID numbers, home addresses, etc. Default false, ie. enable sensitization.
- */
- skipInfoMask?: boolean;
-
- /**
- * Whether to use the standard SSE format, when set to true,
- * the streaming results will be separated by two line breaks.
- * This parameter only takes effect when stream is set to true.
- */
- useStandardSse?: boolean;
-
- /**
- * If it is true, this indicates that the current request is set to continuation mode,
- * and the response is a continuation of the last sentence in the incoming messages;
- * at this time, the last sender is not limited to USER, it can also be BOT.
- * Assuming the last sentence of incoming messages is {"sender_type": " U S E R", "text": "天生我材"},
- * the completion of the reply may be "It must be useful."
- */
- continueLastMessage?: boolean;
-
- /**
- * How many results to generate; the default is 1 and the maximum is not more than 4.
- * Because beamWidth generates multiple results, it will consume more tokens.
- */
- beamWidth?: number;
-
- /**
- * Dialogue Metadata
- */
- roleMeta?: RoleMeta;
-}
-
-declare interface MinimaxChatInputPro extends MinimaxChatInputBase {
- /**
- * For the text information in the output that may involve privacy issues,
- * code masking is currently included but not limited to emails, domains, links, ID numbers, home addresses, etc.,
- * with the default being true, that is, code masking is enabled.
- */
- maskSensitiveInfo?: boolean;
-
- /**
- * Default bot name
- */
- defaultBotName?: string;
-
- /**
- * Default user name
- */
- defaultUserName?: string;
-
- /**
- * Setting for each robot, only available for pro version.
- */
- botSetting?: BotSetting[];
-
- replyConstraints?: ReplyConstraints;
-}
-
-type MinimaxChatInput = MinimaxChatInputNormal & MinimaxChatInputPro;
-
-/**
- * Function that extracts the custom sender_type of a generic chat message.
- * @param message Chat message from which to extract the custom sender_type.
- * @returns The custom sender_type of the chat message.
- */
-function extractGenericMessageCustomRole(message: ChatMessage) {
- if (message.role !== "ai" && message.role !== "user") {
- console.warn(`Unknown message role: ${message.role}`);
- }
- if (message.role === "ai") {
- return "BOT" as MinimaxMessageRole;
- }
- if (message.role === "user") {
- return "USER" as MinimaxMessageRole;
- }
- return message.role as MinimaxMessageRole;
-}
-
-/**
- * Function that converts a base message to a Minimax message sender_type.
- * @param message Base message to convert.
- * @returns The Minimax message sender_type.
- */
-function messageToMinimaxRole(message: BaseMessage): MinimaxMessageRole {
- const type = message._getType();
- switch (type) {
- case "ai":
- return "BOT";
- case "human":
- return "USER";
- case "system":
- throw new Error("System messages not supported");
- case "function":
- return "FUNCTION";
- case "generic": {
- if (!ChatMessage.isInstance(message))
- throw new Error("Invalid generic chat message");
- return extractGenericMessageCustomRole(message);
- }
- default:
- throw new Error(`Unknown message type: ${type}`);
- }
-}
-
-export interface ChatMinimaxCallOptions extends BaseFunctionCallOptions {
- tools?: StructuredTool[];
- defaultUserName?: string;
- defaultBotName?: string;
- plugins?: string[];
- botSetting?: BotSetting[];
- replyConstraints?: ReplyConstraints;
- sampleMessages?: BaseMessage[];
-}
-
-/**
- * Wrapper around Minimax large language models that use the Chat endpoint.
- *
- * To use you should have the `MINIMAX_GROUP_ID` and `MINIMAX_API_KEY`
- * environment variable set.
- * @example
- * ```typescript
- * // Define a chat prompt with a system message setting the context for translation
- * const chatPrompt = ChatPromptTemplate.fromMessages([
- * SystemMessagePromptTemplate.fromTemplate(
- * "You are a helpful assistant that translates {input_language} to {output_language}.",
- * ),
- * HumanMessagePromptTemplate.fromTemplate("{text}"),
- * ]);
- *
- * // Create a new LLMChain with the chat model and the defined prompt
- * const chainB = new LLMChain({
- * prompt: chatPrompt,
- * llm: new ChatMinimax({ temperature: 0.01 }),
- * });
- *
- * // Call the chain with the input language, output language, and the text to translate
- * const resB = await chainB.call({
- * input_language: "English",
- * output_language: "Chinese",
- * text: "I love programming.",
- * });
- *
- * // Log the result
- * console.log({ resB });
- *
- * ```
- */
-export class ChatMinimax
- extends BaseChatModel
- implements MinimaxChatInput
-{
- static lc_name() {
- return "ChatMinimax";
- }
-
- get callKeys(): (keyof ChatMinimaxCallOptions)[] {
- return [
- ...(super.callKeys as (keyof ChatMinimaxCallOptions)[]),
- "functions",
- "tools",
- "defaultBotName",
- "defaultUserName",
- "plugins",
- "replyConstraints",
- "botSetting",
- "sampleMessages",
- ];
- }
-
- get lc_secrets(): { [key: string]: string } | undefined {
- return {
- minimaxApiKey: "MINIMAX_API_KEY",
- minimaxGroupId: "MINIMAX_GROUP_ID",
- };
- }
-
- lc_serializable = true;
-
- minimaxGroupId?: string;
-
- minimaxApiKey?: string;
-
- streaming = false;
-
- prompt?: string;
-
- modelName = "abab5.5-chat";
-
- defaultBotName?: string = "Assistant";
-
- defaultUserName?: string = "I";
-
- prefixMessages?: MinimaxChatCompletionRequestMessage[];
-
- apiUrl: string;
-
- basePath?: string = "https://api.minimax.chat/v1";
-
- headers?: Record;
-
- temperature?: number = 0.9;
-
- topP?: number = 0.8;
-
- tokensToGenerate?: number;
-
- skipInfoMask?: boolean;
-
- proVersion?: boolean = true;
-
- beamWidth?: number;
-
- botSetting?: BotSetting[];
-
- continueLastMessage?: boolean;
-
- maskSensitiveInfo?: boolean;
-
- roleMeta?: RoleMeta;
-
- useStandardSse?: boolean;
-
- replyConstraints?: ReplyConstraints;
-
- constructor(
- fields?: Partial &
- BaseChatModelParams & {
- configuration?: ConfigurationParameters;
- }
- ) {
- super(fields ?? {});
-
- this.minimaxGroupId =
- fields?.minimaxGroupId ?? getEnvironmentVariable("MINIMAX_GROUP_ID");
- if (!this.minimaxGroupId) {
- throw new Error("Minimax GroupID not found");
- }
-
- this.minimaxApiKey =
- fields?.minimaxApiKey ?? getEnvironmentVariable("MINIMAX_API_KEY");
-
- if (!this.minimaxApiKey) {
- throw new Error("Minimax ApiKey not found");
- }
-
- this.streaming = fields?.streaming ?? this.streaming;
- this.prompt = fields?.prompt ?? this.prompt;
- this.temperature = fields?.temperature ?? this.temperature;
- this.topP = fields?.topP ?? this.topP;
- this.skipInfoMask = fields?.skipInfoMask ?? this.skipInfoMask;
- this.prefixMessages = fields?.prefixMessages ?? this.prefixMessages;
- this.maskSensitiveInfo =
- fields?.maskSensitiveInfo ?? this.maskSensitiveInfo;
- this.beamWidth = fields?.beamWidth ?? this.beamWidth;
- this.continueLastMessage =
- fields?.continueLastMessage ?? this.continueLastMessage;
- this.tokensToGenerate = fields?.tokensToGenerate ?? this.tokensToGenerate;
- this.roleMeta = fields?.roleMeta ?? this.roleMeta;
- this.botSetting = fields?.botSetting ?? this.botSetting;
- this.useStandardSse = fields?.useStandardSse ?? this.useStandardSse;
- this.replyConstraints = fields?.replyConstraints ?? this.replyConstraints;
- this.defaultBotName = fields?.defaultBotName ?? this.defaultBotName;
-
- this.modelName = fields?.modelName ?? this.modelName;
- this.basePath = fields?.configuration?.basePath ?? this.basePath;
- this.headers = fields?.configuration?.headers ?? this.headers;
- this.proVersion = fields?.proVersion ?? this.proVersion;
-
- const modelCompletion = this.proVersion
- ? "chatcompletion_pro"
- : "chatcompletion";
- this.apiUrl = `${this.basePath}/text/${modelCompletion}`;
- }
-
- fallbackBotName(options?: this["ParsedCallOptions"]) {
- let botName = options?.defaultBotName ?? this.defaultBotName ?? "Assistant";
- if (this.botSetting) {
- botName = this.botSetting[0].bot_name;
- }
- return botName;
- }
-
- defaultReplyConstraints(options?: this["ParsedCallOptions"]) {
- const constraints = options?.replyConstraints ?? this.replyConstraints;
- if (!constraints) {
- let botName =
- options?.defaultBotName ?? this.defaultBotName ?? "Assistant";
- if (this.botSetting) {
- botName = this.botSetting[0].bot_name;
- }
-
- return {
- sender_type: "BOT",
- sender_name: botName,
- };
- }
- return constraints;
- }
-
- /**
- * Get the parameters used to invoke the model
- */
- invocationParams(
- options?: this["ParsedCallOptions"]
- ): Omit {
- return {
- model: this.modelName,
- stream: this.streaming,
- prompt: this.prompt,
- temperature: this.temperature,
- top_p: this.topP,
- tokens_to_generate: this.tokensToGenerate,
- skip_info_mask: this.skipInfoMask,
- mask_sensitive_info: this.maskSensitiveInfo,
- beam_width: this.beamWidth,
- use_standard_sse: this.useStandardSse,
- role_meta: this.roleMeta,
- bot_setting: options?.botSetting ?? this.botSetting,
- reply_constraints: this.defaultReplyConstraints(options),
- sample_messages: this.messageToMinimaxMessage(
- options?.sampleMessages,
- options
- ),
- functions:
- options?.functions ??
- (options?.tools
- ? options?.tools.map(formatToOpenAIFunction)
- : undefined),
- plugins: options?.plugins,
- };
- }
-
- /**
- * Get the identifying parameters for the model
- */
- identifyingParams() {
- return {
- ...this.invocationParams(),
- };
- }
-
- /**
- * Convert a list of messages to the format expected by the model.
- * @param messages
- * @param options
- */
- messageToMinimaxMessage(
- messages?: BaseMessage[],
- options?: this["ParsedCallOptions"]
- ): MinimaxChatCompletionRequestMessage[] | undefined {
- return messages
- ?.filter((message) => {
- if (ChatMessage.isInstance(message)) {
- return message.role !== "system";
- }
- return message._getType() !== "system";
- })
- ?.map((message) => {
- const sender_type = messageToMinimaxRole(message);
- if (typeof message.content !== "string") {
- throw new Error(
- "ChatMinimax does not support non-string message content."
- );
- }
- return {
- sender_type,
- text: message.content,
- sender_name:
- message.name ??
- (sender_type === "BOT"
- ? this.fallbackBotName()
- : options?.defaultUserName ?? this.defaultUserName),
- };
- });
- }
-
- /** @ignore */
- async _generate(
- messages: BaseMessage[],
- options?: this["ParsedCallOptions"],
- runManager?: CallbackManagerForLLMRun
- ): Promise {
- const tokenUsage = { totalTokens: 0 };
- this.botSettingFallback(options, messages);
-
- const params = this.invocationParams(options);
- const messagesMapped: MinimaxChatCompletionRequestMessage[] = [
- ...(this.messageToMinimaxMessage(messages, options) ?? []),
- ...(this.prefixMessages ?? []),
- ];
-
- const data = params.stream
- ? await new Promise((resolve, reject) => {
- let response: ChatCompletionResponse;
- let rejected = false;
- let resolved = false;
- this.completionWithRetry(
- {
- ...params,
- messages: messagesMapped,
- },
- true,
- options?.signal,
- (event) => {
- const data = JSON.parse(event.data);
-
- if (data?.error_code) {
- if (rejected) {
- return;
- }
- rejected = true;
- reject(data);
- return;
- }
-
- const message = data as ChatCompletionResponse;
- // on the first message set the response properties
-
- if (!message.choices[0].finish_reason) {
- // the last stream message
- let streamText;
- if (this.proVersion) {
- const messages = message.choices[0].messages ?? [];
- streamText = messages[0].text;
- } else {
- streamText = message.choices[0].delta;
- }
-
- // TODO this should pass part.index to the callback
- // when that's supported there
- // eslint-disable-next-line no-void
- void runManager?.handleLLMNewToken(streamText ?? "");
- return;
- }
-
- response = message;
- if (!this.proVersion) {
- response.choices[0].text = message.reply;
- }
-
- if (resolved || rejected) {
- return;
- }
- resolved = true;
- resolve(response);
- }
- ).catch((error) => {
- if (!rejected) {
- rejected = true;
- reject(error);
- }
- });
- })
- : await this.completionWithRetry(
- {
- ...params,
- messages: messagesMapped,
- },
- false,
- options?.signal
- );
-
- const { total_tokens: totalTokens } = data.usage ?? {};
-
- if (totalTokens) {
- tokenUsage.totalTokens = totalTokens;
- }
-
- if (data.base_resp?.status_code !== 0) {
- throw new Error(`Minimax API error: ${data.base_resp?.status_msg}`);
- }
- const generations: ChatGeneration[] = [];
-
- if (this.proVersion) {
- for (const choice of data.choices) {
- const messages = choice.messages ?? [];
- // 取最后一条消息
- if (messages) {
- const message = messages[messages.length - 1];
- const text = message?.text ?? "";
- generations.push({
- text,
- message: minimaxResponseToChatMessage(message),
- });
- }
- }
- } else {
- for (const choice of data.choices) {
- const text = choice?.text ?? "";
- generations.push({
- text,
- message: minimaxResponseToChatMessage({
- sender_type: "BOT",
- sender_name:
- options?.defaultBotName ?? this.defaultBotName ?? "Assistant",
- text,
- }),
- });
- }
- }
- return {
- generations,
- llmOutput: { tokenUsage },
- };
- }
-
- /** @ignore */
- async completionWithRetry(
- request: MinimaxChatCompletionRequest,
- stream: boolean,
- signal?: AbortSignal,
- onmessage?: (event: MessageEvent) => void
- ) {
- // The first run will get the accessToken
- const makeCompletionRequest = async () => {
- const url = `${this.apiUrl}?GroupId=${this.minimaxGroupId}`;
- const response = await fetch(url, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- Authorization: `Bearer ${this.minimaxApiKey}`,
- ...this.headers,
- },
- body: JSON.stringify(request),
- signal,
- });
-
- if (!stream) {
- const json = await response.json();
- return json as ChatCompletionResponse;
- } else {
- if (response.body) {
- const reader = response.body.getReader();
-
- const decoder = new TextDecoder("utf-8");
- let data = "";
-
- let continueReading = true;
- while (continueReading) {
- const { done, value } = await reader.read();
- if (done) {
- continueReading = false;
- break;
- }
- data += decoder.decode(value);
-
- let continueProcessing = true;
- while (continueProcessing) {
- const newlineIndex = data.indexOf("\n");
- if (newlineIndex === -1) {
- continueProcessing = false;
- break;
- }
- const line = data.slice(0, newlineIndex);
- data = data.slice(newlineIndex + 1);
-
- if (line.startsWith("data:")) {
- const event = new MessageEvent("message", {
- data: line.slice("data:".length).trim(),
- });
- onmessage?.(event);
- }
- }
- }
- return {} as ChatCompletionResponse;
- }
- return {} as ChatCompletionResponse;
- }
- };
- return this.caller.call(makeCompletionRequest);
- }
-
- _llmType() {
- return "minimax";
- }
-
- /** @ignore */
- _combineLLMOutput() {
- return [];
- }
-
- private botSettingFallback(
- options?: this["ParsedCallOptions"],
- messages?: BaseMessage[]
- ) {
- const botSettings = options?.botSetting ?? this.botSetting;
- if (!botSettings) {
- const systemMessages = messages?.filter((message) => {
- if (ChatMessage.isInstance(message)) {
- return message.role === "system";
- }
- return message._getType() === "system";
- });
-
- // get the last system message
- if (!systemMessages?.length) {
- return;
- }
- const lastSystemMessage = systemMessages[systemMessages.length - 1];
-
- if (typeof lastSystemMessage.content !== "string") {
- throw new Error(
- "ChatMinimax does not support non-string message content."
- );
- }
-
- // setting the default botSetting.
- this.botSetting = [
- {
- content: lastSystemMessage.content,
- bot_name:
- options?.defaultBotName ?? this.defaultBotName ?? "Assistant",
- },
- ];
- }
- }
-}
-
-function minimaxResponseToChatMessage(
- message: ChatCompletionResponseMessage
-): BaseMessage {
- switch (message.sender_type) {
- case "USER":
- return new HumanMessage(message.text || "");
- case "BOT":
- return new AIMessage(message.text || "", {
- function_call: message.function_call,
- });
- case "FUNCTION":
- return new AIMessage(message.text || "");
- default:
- return new ChatMessage(
- message.text || "",
- message.sender_type ?? "unknown"
- );
- }
-}
-
-/** ---Response Model---* */
-/**
- * Interface representing a message responsed in the Minimax chat model.
- */
-interface ChatCompletionResponseMessage {
- sender_type: MinimaxMessageRole;
- sender_name?: string;
- text: string;
- function_call?: ChatCompletionResponseMessageFunctionCall;
-}
-
-/**
- * Interface representing the usage of tokens in a chat completion.
- */
-interface TokenUsage {
- total_tokens?: number;
-}
-
-interface BaseResp {
- status_code?: number;
- status_msg?: string;
-}
-
-/**
- * The name and arguments of a function that should be called, as generated by the model.
- * @export
- * @interface ChatCompletionResponseMessageFunctionCall
- */
-export interface ChatCompletionResponseMessageFunctionCall {
- /**
- * The name of the function to call.
- * @type {string}
- * @memberof ChatCompletionResponseMessageFunctionCall
- */
- name?: string;
- /**
- * The arguments to call the function with, as generated by the model in JSON format. Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your function schema. Validate the arguments in your code before calling your function.
- * @type {string}
- * @memberof ChatCompletionResponseMessageFunctionCall
- */
- arguments?: string;
-}
-
-/**
- *
- * @export
- * @interface ChatCompletionResponseChoices
- */
-export interface ChatCompletionResponseChoicesPro {
- /**
- *
- * @type {string}
- * @memberof ChatCompletionResponseChoices
- */
- messages?: ChatCompletionResponseMessage[];
-
- /**
- *
- * @type {string}
- * @memberof ChatCompletionResponseChoices
- */
- finish_reason?: string;
-}
-
-interface ChatCompletionResponseChoices {
- delta?: string;
- text?: string;
- index?: number;
- finish_reason?: string;
-}
-
-/**
- * Interface representing a response from a chat completion.
- */
-interface ChatCompletionResponse {
- model: string;
- created: number;
- reply: string;
- input_sensitive?: boolean;
- input_sensitive_type?: number;
- output_sensitive?: boolean;
- output_sensitive_type?: number;
- usage?: TokenUsage;
- base_resp?: BaseResp;
- choices: Array<
- ChatCompletionResponseChoicesPro & ChatCompletionResponseChoices
- >;
-}
+export * from "@langchain/community/chat_models/minimax";
diff --git a/langchain/src/chat_models/ollama.ts b/langchain/src/chat_models/ollama.ts
index a3fbdb367eb2..175e84ab3511 100644
--- a/langchain/src/chat_models/ollama.ts
+++ b/langchain/src/chat_models/ollama.ts
@@ -1,298 +1 @@
-import { SimpleChatModel, BaseChatModelParams } from "./base.js";
-import { BaseLanguageModelCallOptions } from "../base_language/index.js";
-import { createOllamaStream, OllamaInput } from "../util/ollama.js";
-import { CallbackManagerForLLMRun } from "../callbacks/manager.js";
-import {
- AIMessageChunk,
- BaseMessage,
- ChatGenerationChunk,
- ChatMessage,
-} from "../schema/index.js";
-import type { StringWithAutocomplete } from "../util/types.js";
-
-/**
- * An interface defining the options for an Ollama API call. It extends
- * the BaseLanguageModelCallOptions interface.
- */
-export interface OllamaCallOptions extends BaseLanguageModelCallOptions {}
-
-/**
- * A class that enables calls to the Ollama API to access large language
- * models in a chat-like fashion. It extends the SimpleChatModel class and
- * implements the OllamaInput interface.
- * @example
- * ```typescript
- * const prompt = ChatPromptTemplate.fromMessages([
- * [
- * "system",
- * `You are an expert translator. Format all responses as JSON objects with two keys: "original" and "translated".`,
- * ],
- * ["human", `Translate "{input}" into {language}.`],
- * ]);
- *
- * const model = new ChatOllama({
- * baseUrl: "http://api.example.com",
- * model: "llama2",
- * format: "json",
- * });
- *
- * const chain = prompt.pipe(model);
- *
- * const result = await chain.invoke({
- * input: "I love programming",
- * language: "German",
- * });
- *
- * ```
- */
-export class ChatOllama
- extends SimpleChatModel
- implements OllamaInput
-{
- static lc_name() {
- return "ChatOllama";
- }
-
- lc_serializable = true;
-
- model = "llama2";
-
- baseUrl = "http://localhost:11434";
-
- embeddingOnly?: boolean;
-
- f16KV?: boolean;
-
- frequencyPenalty?: number;
-
- logitsAll?: boolean;
-
- lowVram?: boolean;
-
- mainGpu?: number;
-
- mirostat?: number;
-
- mirostatEta?: number;
-
- mirostatTau?: number;
-
- numBatch?: number;
-
- numCtx?: number;
-
- numGpu?: number;
-
- numGqa?: number;
-
- numKeep?: number;
-
- numThread?: number;
-
- penalizeNewline?: boolean;
-
- presencePenalty?: number;
-
- repeatLastN?: number;
-
- repeatPenalty?: number;
-
- ropeFrequencyBase?: number;
-
- ropeFrequencyScale?: number;
-
- temperature?: number;
-
- stop?: string[];
-
- tfsZ?: number;
-
- topK?: number;
-
- topP?: number;
-
- typicalP?: number;
-
- useMLock?: boolean;
-
- useMMap?: boolean;
-
- vocabOnly?: boolean;
-
- format?: StringWithAutocomplete<"json">;
-
- constructor(fields: OllamaInput & BaseChatModelParams) {
- super(fields);
- this.model = fields.model ?? this.model;
- this.baseUrl = fields.baseUrl?.endsWith("/")
- ? fields.baseUrl.slice(0, -1)
- : fields.baseUrl ?? this.baseUrl;
- this.embeddingOnly = fields.embeddingOnly;
- this.f16KV = fields.f16KV;
- this.frequencyPenalty = fields.frequencyPenalty;
- this.logitsAll = fields.logitsAll;
- this.lowVram = fields.lowVram;
- this.mainGpu = fields.mainGpu;
- this.mirostat = fields.mirostat;
- this.mirostatEta = fields.mirostatEta;
- this.mirostatTau = fields.mirostatTau;
- this.numBatch = fields.numBatch;
- this.numCtx = fields.numCtx;
- this.numGpu = fields.numGpu;
- this.numGqa = fields.numGqa;
- this.numKeep = fields.numKeep;
- this.numThread = fields.numThread;
- this.penalizeNewline = fields.penalizeNewline;
- this.presencePenalty = fields.presencePenalty;
- this.repeatLastN = fields.repeatLastN;
- this.repeatPenalty = fields.repeatPenalty;
- this.ropeFrequencyBase = fields.ropeFrequencyBase;
- this.ropeFrequencyScale = fields.ropeFrequencyScale;
- this.temperature = fields.temperature;
- this.stop = fields.stop;
- this.tfsZ = fields.tfsZ;
- this.topK = fields.topK;
- this.topP = fields.topP;
- this.typicalP = fields.typicalP;
- this.useMLock = fields.useMLock;
- this.useMMap = fields.useMMap;
- this.vocabOnly = fields.vocabOnly;
- this.format = fields.format;
- }
-
- _llmType() {
- return "ollama";
- }
-
- /**
- * A method that returns the parameters for an Ollama API call. It
- * includes model and options parameters.
- * @param options Optional parsed call options.
- * @returns An object containing the parameters for an Ollama API call.
- */
- invocationParams(options?: this["ParsedCallOptions"]) {
- return {
- model: this.model,
- format: this.format,
- options: {
- embedding_only: this.embeddingOnly,
- f16_kv: this.f16KV,
- frequency_penalty: this.frequencyPenalty,
- logits_all: this.logitsAll,
- low_vram: this.lowVram,
- main_gpu: this.mainGpu,
- mirostat: this.mirostat,
- mirostat_eta: this.mirostatEta,
- mirostat_tau: this.mirostatTau,
- num_batch: this.numBatch,
- num_ctx: this.numCtx,
- num_gpu: this.numGpu,
- num_gqa: this.numGqa,
- num_keep: this.numKeep,
- num_thread: this.numThread,
- penalize_newline: this.penalizeNewline,
- presence_penalty: this.presencePenalty,
- repeat_last_n: this.repeatLastN,
- repeat_penalty: this.repeatPenalty,
- rope_frequency_base: this.ropeFrequencyBase,
- rope_frequency_scale: this.ropeFrequencyScale,
- temperature: this.temperature,
- stop: options?.stop ?? this.stop,
- tfs_z: this.tfsZ,
- top_k: this.topK,
- top_p: this.topP,
- typical_p: this.typicalP,
- use_mlock: this.useMLock,
- use_mmap: this.useMMap,
- vocab_only: this.vocabOnly,
- },
- };
- }
-
- _combineLLMOutput() {
- return {};
- }
-
- async *_streamResponseChunks(
- input: BaseMessage[],
- options: this["ParsedCallOptions"],
- runManager?: CallbackManagerForLLMRun
- ): AsyncGenerator {
- const stream = await this.caller.call(async () =>
- createOllamaStream(
- this.baseUrl,
- {
- ...this.invocationParams(options),
- prompt: this._formatMessagesAsPrompt(input),
- },
- options
- )
- );
- for await (const chunk of stream) {
- if (!chunk.done) {
- yield new ChatGenerationChunk({
- text: chunk.response,
- message: new AIMessageChunk({ content: chunk.response }),
- });
- await runManager?.handleLLMNewToken(chunk.response ?? "");
- } else {
- yield new ChatGenerationChunk({
- text: "",
- message: new AIMessageChunk({ content: "" }),
- generationInfo: {
- model: chunk.model,
- total_duration: chunk.total_duration,
- load_duration: chunk.load_duration,
- prompt_eval_count: chunk.prompt_eval_count,
- prompt_eval_duration: chunk.prompt_eval_duration,
- eval_count: chunk.eval_count,
- eval_duration: chunk.eval_duration,
- },
- });
- }
- }
- }
-
- protected _formatMessagesAsPrompt(messages: BaseMessage[]): string {
- const formattedMessages = messages
- .map((message) => {
- let messageText;
- if (message._getType() === "human") {
- messageText = `[INST] ${message.content} [/INST]`;
- } else if (message._getType() === "ai") {
- messageText = message.content;
- } else if (message._getType() === "system") {
- messageText = `<> ${message.content} <>`;
- } else if (ChatMessage.isInstance(message)) {
- messageText = `\n\n${message.role[0].toUpperCase()}${message.role.slice(
- 1
- )}: ${message.content}`;
- } else {
- console.warn(
- `Unsupported message type passed to Ollama: "${message._getType()}"`
- );
- messageText = "";
- }
- return messageText;
- })
- .join("\n");
- return formattedMessages;
- }
-
- /** @ignore */
- async _call(
- messages: BaseMessage[],
- options: this["ParsedCallOptions"],
- runManager?: CallbackManagerForLLMRun
- ): Promise {
- const chunks = [];
- for await (const chunk of this._streamResponseChunks(
- messages,
- options,
- runManager
- )) {
- chunks.push(chunk.message.content);
- }
- return chunks.join("");
- }
-}
+export * from "@langchain/community/chat_models/ollama";
diff --git a/langchain/src/chat_models/openai.ts b/langchain/src/chat_models/openai.ts
index c8e99c525246..cf822cb30a8d 100644
--- a/langchain/src/chat_models/openai.ts
+++ b/langchain/src/chat_models/openai.ts
@@ -1,836 +1,20 @@
-import { type ClientOptions, OpenAI as OpenAIClient } from "openai";
+import {
+ ChatOpenAI,
+ type ChatOpenAICallOptions,
+ messageToOpenAIRole,
+} from "@langchain/openai";
import { CallbackManagerForLLMRun } from "../callbacks/manager.js";
-import {
- AIMessage,
- AIMessageChunk,
- BaseMessage,
- ChatGeneration,
- ChatGenerationChunk,
- ChatMessage,
- ChatMessageChunk,
- ChatResult,
- FunctionMessageChunk,
- HumanMessageChunk,
- SystemMessageChunk,
- ToolMessage,
- ToolMessageChunk,
-} from "../schema/index.js";
-import { StructuredTool } from "../tools/base.js";
-import { formatToOpenAITool } from "../tools/convert_to_openai.js";
-import {
- AzureOpenAIInput,
- OpenAICallOptions,
- OpenAIChatInput,
- OpenAICoreRequestOptions,
- LegacyOpenAIInput,
-} from "../types/openai-types.js";
-import { OpenAIEndpointConfig, getEndpoint } from "../util/azure.js";
-import { getEnvironmentVariable } from "../util/env.js";
+import { BaseMessage, ChatMessage, ChatResult } from "../schema/index.js";
import { promptLayerTrackRequest } from "../util/prompt-layer.js";
-import { BaseChatModel, BaseChatModelParams } from "./base.js";
-import { BaseFunctionCallOptions } from "../base_language/index.js";
-import { NewTokenIndices } from "../callbacks/base.js";
-import { wrapOpenAIClientError } from "../util/openai.js";
-import {
- FunctionDef,
- formatFunctionDefinitions,
-} from "../util/openai-format-fndef.js";
-
-export type { AzureOpenAIInput, OpenAICallOptions, OpenAIChatInput };
-
-interface TokenUsage {
- completionTokens?: number;
- promptTokens?: number;
- totalTokens?: number;
-}
-
-interface OpenAILLMOutput {
- tokenUsage: TokenUsage;
-}
-
-// TODO import from SDK when available
-type OpenAIRoleEnum = "system" | "assistant" | "user" | "function" | "tool";
-
-type OpenAICompletionParam =
- OpenAIClient.Chat.Completions.ChatCompletionMessageParam;
-type OpenAIFnDef = OpenAIClient.Chat.ChatCompletionCreateParams.Function;
-type OpenAIFnCallOption = OpenAIClient.Chat.ChatCompletionFunctionCallOption;
-
-function extractGenericMessageCustomRole(message: ChatMessage) {
- if (
- message.role !== "system" &&
- message.role !== "assistant" &&
- message.role !== "user" &&
- message.role !== "function" &&
- message.role !== "tool"
- ) {
- console.warn(`Unknown message role: ${message.role}`);
- }
-
- return message.role as OpenAIRoleEnum;
-}
-
-function messageToOpenAIRole(message: BaseMessage): OpenAIRoleEnum {
- const type = message._getType();
- switch (type) {
- case "system":
- return "system";
- case "ai":
- return "assistant";
- case "human":
- return "user";
- case "function":
- return "function";
- case "tool":
- return "tool";
- case "generic": {
- if (!ChatMessage.isInstance(message))
- throw new Error("Invalid generic chat message");
- return extractGenericMessageCustomRole(message);
- }
- default:
- throw new Error(`Unknown message type: ${type}`);
- }
-}
-
-function openAIResponseToChatMessage(
- message: OpenAIClient.Chat.Completions.ChatCompletionMessage
-): BaseMessage {
- switch (message.role) {
- case "assistant":
- return new AIMessage(message.content || "", {
- function_call: message.function_call,
- tool_calls: message.tool_calls,
- });
- default:
- return new ChatMessage(message.content || "", message.role ?? "unknown");
- }
-}
-
-function _convertDeltaToMessageChunk(
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- delta: Record,
- defaultRole?: OpenAIRoleEnum
-) {
- const role = delta.role ?? defaultRole;
- const content = delta.content ?? "";
- let additional_kwargs;
- if (delta.function_call) {
- additional_kwargs = {
- function_call: delta.function_call,
- };
- } else if (delta.tool_calls) {
- additional_kwargs = {
- tool_calls: delta.tool_calls,
- };
- } else {
- additional_kwargs = {};
- }
- if (role === "user") {
- return new HumanMessageChunk({ content });
- } else if (role === "assistant") {
- return new AIMessageChunk({ content, additional_kwargs });
- } else if (role === "system") {
- return new SystemMessageChunk({ content });
- } else if (role === "function") {
- return new FunctionMessageChunk({
- content,
- additional_kwargs,
- name: delta.name,
- });
- } else if (role === "tool") {
- return new ToolMessageChunk({
- content,
- additional_kwargs,
- tool_call_id: delta.tool_call_id,
- });
- } else {
- return new ChatMessageChunk({ content, role });
- }
-}
-
-function convertMessagesToOpenAIParams(messages: BaseMessage[]) {
- // TODO: Function messages do not support array content, fix cast
- return messages.map(
- (message) =>
- ({
- role: messageToOpenAIRole(message),
- content: message.content,
- name: message.name,
- function_call: message.additional_kwargs.function_call,
- tool_calls: message.additional_kwargs.tool_calls,
- tool_call_id: (message as ToolMessage).tool_call_id,
- } as OpenAICompletionParam)
- );
-}
-
-export interface ChatOpenAICallOptions
- extends OpenAICallOptions,
- BaseFunctionCallOptions {
- tools?: StructuredTool[] | OpenAIClient.ChatCompletionTool[];
- tool_choice?: OpenAIClient.ChatCompletionToolChoiceOption;
- promptIndex?: number;
- response_format?: { type: "json_object" };
- seed?: number;
-}
-
-/**
- * Wrapper around OpenAI large language models that use the Chat endpoint.
- *
- * To use you should have the `openai` package installed, with the
- * `OPENAI_API_KEY` environment variable set.
- *
- * To use with Azure you should have the `openai` package installed, with the
- * `AZURE_OPENAI_API_KEY`,
- * `AZURE_OPENAI_API_INSTANCE_NAME`,
- * `AZURE_OPENAI_API_DEPLOYMENT_NAME`
- * and `AZURE_OPENAI_API_VERSION` environment variable set.
- * `AZURE_OPENAI_BASE_PATH` is optional and will override `AZURE_OPENAI_API_INSTANCE_NAME` if you need to use a custom endpoint.
- *
- * @remarks
- * Any parameters that are valid to be passed to {@link
- * https://platform.openai.com/docs/api-reference/chat/create |
- * `openai.createChatCompletion`} can be passed through {@link modelKwargs}, even
- * if not explicitly available on this class.
- * @example
- * ```typescript
- * // Create a new instance of ChatOpenAI with specific temperature and model name settings
- * const model = new ChatOpenAI({
- * temperature: 0.9,
- * modelName: "ft:gpt-3.5-turbo-0613:{ORG_NAME}::{MODEL_ID}",
- * });
- *
- * // Invoke the model with a message and await the response
- * const message = await model.invoke("Hi there!");
- *
- * // Log the response to the console
- * console.log(message);
- *
- * ```
- */
-export class ChatOpenAI<
- CallOptions extends ChatOpenAICallOptions = ChatOpenAICallOptions
- >
- extends BaseChatModel
- implements OpenAIChatInput, AzureOpenAIInput
-{
- static lc_name() {
- return "ChatOpenAI";
- }
-
- get callKeys() {
- return [
- ...super.callKeys,
- "options",
- "function_call",
- "functions",
- "tools",
- "tool_choice",
- "promptIndex",
- "response_format",
- "seed",
- ];
- }
-
- lc_serializable = true;
-
- get lc_secrets(): { [key: string]: string } | undefined {
- return {
- openAIApiKey: "OPENAI_API_KEY",
- azureOpenAIApiKey: "AZURE_OPENAI_API_KEY",
- organization: "OPENAI_ORGANIZATION",
- };
- }
-
- get lc_aliases(): Record {
- return {
- modelName: "model",
- openAIApiKey: "openai_api_key",
- azureOpenAIApiVersion: "azure_openai_api_version",
- azureOpenAIApiKey: "azure_openai_api_key",
- azureOpenAIApiInstanceName: "azure_openai_api_instance_name",
- azureOpenAIApiDeploymentName: "azure_openai_api_deployment_name",
- };
- }
-
- temperature = 1;
-
- topP = 1;
-
- frequencyPenalty = 0;
-
- presencePenalty = 0;
-
- n = 1;
-
- logitBias?: Record;
-
- modelName = "gpt-3.5-turbo";
- modelKwargs?: OpenAIChatInput["modelKwargs"];
-
- stop?: string[];
-
- user?: string;
-
- timeout?: number;
-
- streaming = false;
-
- maxTokens?: number;
-
- openAIApiKey?: string;
-
- azureOpenAIApiVersion?: string;
-
- azureOpenAIApiKey?: string;
-
- azureOpenAIApiInstanceName?: string;
-
- azureOpenAIApiDeploymentName?: string;
-
- azureOpenAIBasePath?: string;
-
- organization?: string;
-
- private client: OpenAIClient;
-
- private clientConfig: ClientOptions;
-
- constructor(
- fields?: Partial &
- Partial &
- BaseChatModelParams & {
- configuration?: ClientOptions & LegacyOpenAIInput;
- },
- /** @deprecated */
- configuration?: ClientOptions & LegacyOpenAIInput
- ) {
- super(fields ?? {});
-
- this.openAIApiKey =
- fields?.openAIApiKey ?? getEnvironmentVariable("OPENAI_API_KEY");
-
- this.azureOpenAIApiKey =
- fields?.azureOpenAIApiKey ??
- getEnvironmentVariable("AZURE_OPENAI_API_KEY");
-
- if (!this.azureOpenAIApiKey && !this.openAIApiKey) {
- throw new Error("OpenAI or Azure OpenAI API key not found");
- }
-
- this.azureOpenAIApiInstanceName =
- fields?.azureOpenAIApiInstanceName ??
- getEnvironmentVariable("AZURE_OPENAI_API_INSTANCE_NAME");
-
- this.azureOpenAIApiDeploymentName =
- fields?.azureOpenAIApiDeploymentName ??
- getEnvironmentVariable("AZURE_OPENAI_API_DEPLOYMENT_NAME");
-
- this.azureOpenAIApiVersion =
- fields?.azureOpenAIApiVersion ??
- getEnvironmentVariable("AZURE_OPENAI_API_VERSION");
-
- this.azureOpenAIBasePath =
- fields?.azureOpenAIBasePath ??
- getEnvironmentVariable("AZURE_OPENAI_BASE_PATH");
-
- this.organization =
- fields?.configuration?.organization ??
- getEnvironmentVariable("OPENAI_ORGANIZATION");
-
- this.modelName = fields?.modelName ?? this.modelName;
- this.modelKwargs = fields?.modelKwargs ?? {};
- this.timeout = fields?.timeout;
-
- this.temperature = fields?.temperature ?? this.temperature;
- this.topP = fields?.topP ?? this.topP;
- this.frequencyPenalty = fields?.frequencyPenalty ?? this.frequencyPenalty;
- this.presencePenalty = fields?.presencePenalty ?? this.presencePenalty;
- this.maxTokens = fields?.maxTokens;
- this.n = fields?.n ?? this.n;
- this.logitBias = fields?.logitBias;
- this.stop = fields?.stop;
- this.user = fields?.user;
-
- this.streaming = fields?.streaming ?? false;
-
- if (this.azureOpenAIApiKey) {
- if (!this.azureOpenAIApiInstanceName && !this.azureOpenAIBasePath) {
- throw new Error("Azure OpenAI API instance name not found");
- }
- if (!this.azureOpenAIApiDeploymentName) {
- throw new Error("Azure OpenAI API deployment name not found");
- }
- if (!this.azureOpenAIApiVersion) {
- throw new Error("Azure OpenAI API version not found");
- }
- this.openAIApiKey = this.openAIApiKey ?? "";
- }
-
- this.clientConfig = {
- apiKey: this.openAIApiKey,
- organization: this.organization,
- baseURL: configuration?.basePath ?? fields?.configuration?.basePath,
- dangerouslyAllowBrowser: true,
- defaultHeaders:
- configuration?.baseOptions?.headers ??
- fields?.configuration?.baseOptions?.headers,
- defaultQuery:
- configuration?.baseOptions?.params ??
- fields?.configuration?.baseOptions?.params,
- ...configuration,
- ...fields?.configuration,
- };
- }
-
- /**
- * Get the parameters used to invoke the model
- */
- invocationParams(
- options?: this["ParsedCallOptions"]
- ): Omit {
- function isStructuredToolArray(
- tools?: unknown[]
- ): tools is StructuredTool[] {
- return (
- tools !== undefined &&
- tools.every((tool) =>
- Array.isArray((tool as StructuredTool).lc_namespace)
- )
- );
- }
- const params: Omit<
- OpenAIClient.Chat.ChatCompletionCreateParams,
- "messages"
- > = {
- model: this.modelName,
- temperature: this.temperature,
- top_p: this.topP,
- frequency_penalty: this.frequencyPenalty,
- presence_penalty: this.presencePenalty,
- max_tokens: this.maxTokens === -1 ? undefined : this.maxTokens,
- n: this.n,
- logit_bias: this.logitBias,
- stop: options?.stop ?? this.stop,
- user: this.user,
- stream: this.streaming,
- functions: options?.functions,
- function_call: options?.function_call,
- tools: isStructuredToolArray(options?.tools)
- ? options?.tools.map(formatToOpenAITool)
- : options?.tools,
- tool_choice: options?.tool_choice,
- response_format: options?.response_format,
- seed: options?.seed,
- ...this.modelKwargs,
- };
- return params;
- }
-
- /** @ignore */
- _identifyingParams(): Omit<
- OpenAIClient.Chat.ChatCompletionCreateParams,
- "messages"
- > & {
- model_name: string;
- } & ClientOptions {
- return {
- model_name: this.modelName,
- ...this.invocationParams(),
- ...this.clientConfig,
- };
- }
-
- async *_streamResponseChunks(
- messages: BaseMessage[],
- options: this["ParsedCallOptions"],
- runManager?: CallbackManagerForLLMRun
- ): AsyncGenerator {
- const messagesMapped: OpenAICompletionParam[] =
- convertMessagesToOpenAIParams(messages);
- const params = {
- ...this.invocationParams(options),
- messages: messagesMapped,
- stream: true as const,
- };
- let defaultRole: OpenAIRoleEnum | undefined;
- const streamIterable = await this.completionWithRetry(params, options);
- for await (const data of streamIterable) {
- const choice = data?.choices[0];
- if (!choice) {
- continue;
- }
+export {
+ type AzureOpenAIInput,
+ type OpenAICallOptions,
+ type OpenAIChatInput,
+} from "@langchain/openai";
- const { delta } = choice;
- if (!delta) {
- continue;
- }
- const chunk = _convertDeltaToMessageChunk(delta, defaultRole);
- defaultRole = delta.role ?? defaultRole;
- const newTokenIndices = {
- prompt: options.promptIndex ?? 0,
- completion: choice.index ?? 0,
- };
- if (typeof chunk.content !== "string") {
- console.log(
- "[WARNING]: Received non-string content from OpenAI. This is currently not supported."
- );
- continue;
- }
- const generationChunk = new ChatGenerationChunk({
- message: chunk,
- text: chunk.content,
- generationInfo: newTokenIndices,
- });
- yield generationChunk;
- // eslint-disable-next-line no-void
- void runManager?.handleLLMNewToken(
- generationChunk.text ?? "",
- newTokenIndices,
- undefined,
- undefined,
- undefined,
- { chunk: generationChunk }
- );
- }
- if (options.signal?.aborted) {
- throw new Error("AbortError");
- }
- }
-
- /**
- * Get the identifying parameters for the model
- *
- */
- identifyingParams() {
- return this._identifyingParams();
- }
-
- /** @ignore */
- async _generate(
- messages: BaseMessage[],
- options: this["ParsedCallOptions"],
- runManager?: CallbackManagerForLLMRun
- ): Promise {
- const tokenUsage: TokenUsage = {};
- const params = this.invocationParams(options);
- const messagesMapped: OpenAICompletionParam[] =
- convertMessagesToOpenAIParams(messages);
-
- if (params.stream) {
- const stream = this._streamResponseChunks(messages, options, runManager);
- const finalChunks: Record = {};
- for await (const chunk of stream) {
- const index =
- (chunk.generationInfo as NewTokenIndices)?.completion ?? 0;
- if (finalChunks[index] === undefined) {
- finalChunks[index] = chunk;
- } else {
- finalChunks[index] = finalChunks[index].concat(chunk);
- }
- }
- const generations = Object.entries(finalChunks)
- .sort(([aKey], [bKey]) => parseInt(aKey, 10) - parseInt(bKey, 10))
- .map(([_, value]) => value);
-
- const { functions, function_call } = this.invocationParams(options);
-
- // OpenAI does not support token usage report under stream mode,
- // fallback to estimation.
-
- const promptTokenUsage = await this.getEstimatedTokenCountFromPrompt(
- messages,
- functions,
- function_call
- );
- const completionTokenUsage = await this.getNumTokensFromGenerations(
- generations
- );
-
- tokenUsage.promptTokens = promptTokenUsage;
- tokenUsage.completionTokens = completionTokenUsage;
- tokenUsage.totalTokens = promptTokenUsage + completionTokenUsage;
- return { generations, llmOutput: { estimatedTokenUsage: tokenUsage } };
- } else {
- const data = await this.completionWithRetry(
- {
- ...params,
- stream: false,
- messages: messagesMapped,
- },
- {
- signal: options?.signal,
- ...options?.options,
- }
- );
- const {
- completion_tokens: completionTokens,
- prompt_tokens: promptTokens,
- total_tokens: totalTokens,
- } = data?.usage ?? {};
-
- if (completionTokens) {
- tokenUsage.completionTokens =
- (tokenUsage.completionTokens ?? 0) + completionTokens;
- }
-
- if (promptTokens) {
- tokenUsage.promptTokens = (tokenUsage.promptTokens ?? 0) + promptTokens;
- }
-
- if (totalTokens) {
- tokenUsage.totalTokens = (tokenUsage.totalTokens ?? 0) + totalTokens;
- }
-
- const generations: ChatGeneration[] = [];
- for (const part of data?.choices ?? []) {
- const text = part.message?.content ?? "";
- const generation: ChatGeneration = {
- text,
- message: openAIResponseToChatMessage(
- part.message ?? { role: "assistant" }
- ),
- };
- if (part.finish_reason) {
- generation.generationInfo = { finish_reason: part.finish_reason };
- }
- generations.push(generation);
- }
- return {
- generations,
- llmOutput: { tokenUsage },
- };
- }
- }
-
- /**
- * Estimate the number of tokens a prompt will use.
- * Modified from: https://github.com/hmarr/openai-chat-tokens/blob/main/src/index.ts
- */
- private async getEstimatedTokenCountFromPrompt(
- messages: BaseMessage[],
- functions?: OpenAIFnDef[],
- function_call?: "none" | "auto" | OpenAIFnCallOption
- ): Promise {
- // It appears that if functions are present, the first system message is padded with a trailing newline. This
- // was inferred by trying lots of combinations of messages and functions and seeing what the token counts were.
-
- let tokens = (await this.getNumTokensFromMessages(messages)).totalCount;
-
- // If there are functions, add the function definitions as they count towards token usage
- if (functions && function_call !== "auto") {
- const promptDefinitions = formatFunctionDefinitions(
- functions as unknown as FunctionDef[]
- );
- tokens += await this.getNumTokens(promptDefinitions);
- tokens += 9; // Add nine per completion
- }
-
- // If there's a system message _and_ functions are present, subtract four tokens. I assume this is because
- // functions typically add a system message, but reuse the first one if it's already there. This offsets
- // the extra 9 tokens added by the function definitions.
- if (functions && messages.find((m) => m._getType() === "system")) {
- tokens -= 4;
- }
-
- // If function_call is 'none', add one token.
- // If it's a FunctionCall object, add 4 + the number of tokens in the function name.
- // If it's undefined or 'auto', don't add anything.
- if (function_call === "none") {
- tokens += 1;
- } else if (typeof function_call === "object") {
- tokens += (await this.getNumTokens(function_call.name)) + 4;
- }
-
- return tokens;
- }
-
- /**
- * Estimate the number of tokens an array of generations have used.
- */
- private async getNumTokensFromGenerations(generations: ChatGeneration[]) {
- const generationUsages = await Promise.all(
- generations.map(async (generation) => {
- if (generation.message.additional_kwargs?.function_call) {
- return (await this.getNumTokensFromMessages([generation.message]))
- .countPerMessage[0];
- } else {
- return await this.getNumTokens(generation.message.content);
- }
- })
- );
-
- return generationUsages.reduce((a, b) => a + b, 0);
- }
-
- async getNumTokensFromMessages(messages: BaseMessage[]) {
- let totalCount = 0;
- let tokensPerMessage = 0;
- let tokensPerName = 0;
-
- // From: https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb
- if (this.modelName === "gpt-3.5-turbo-0301") {
- tokensPerMessage = 4;
- tokensPerName = -1;
- } else {
- tokensPerMessage = 3;
- tokensPerName = 1;
- }
-
- const countPerMessage = await Promise.all(
- messages.map(async (message) => {
- const textCount = await this.getNumTokens(message.content);
- const roleCount = await this.getNumTokens(messageToOpenAIRole(message));
- const nameCount =
- message.name !== undefined
- ? tokensPerName + (await this.getNumTokens(message.name))
- : 0;
- let count = textCount + tokensPerMessage + roleCount + nameCount;
-
- // From: https://github.com/hmarr/openai-chat-tokens/blob/main/src/index.ts messageTokenEstimate
- const openAIMessage = message;
- if (openAIMessage._getType() === "function") {
- count -= 2;
- }
- if (openAIMessage.additional_kwargs?.function_call) {
- count += 3;
- }
- if (openAIMessage?.additional_kwargs.function_call?.name) {
- count += await this.getNumTokens(
- openAIMessage.additional_kwargs.function_call?.name
- );
- }
- if (openAIMessage.additional_kwargs.function_call?.arguments) {
- count += await this.getNumTokens(
- // Remove newlines and spaces
- JSON.stringify(
- JSON.parse(
- openAIMessage.additional_kwargs.function_call?.arguments
- )
- )
- );
- }
-
- totalCount += count;
- return count;
- })
- );
-
- totalCount += 3; // every reply is primed with <|start|>assistant<|message|>
-
- return { totalCount, countPerMessage };
- }
-
- /**
- * Calls the OpenAI API with retry logic in case of failures.
- * @param request The request to send to the OpenAI API.
- * @param options Optional configuration for the API call.
- * @returns The response from the OpenAI API.
- */
- async completionWithRetry(
- request: OpenAIClient.Chat.ChatCompletionCreateParamsStreaming,
- options?: OpenAICoreRequestOptions
- ): Promise>;
-
- async completionWithRetry(
- request: OpenAIClient.Chat.ChatCompletionCreateParamsNonStreaming,
- options?: OpenAICoreRequestOptions
- ): Promise;
-
- async completionWithRetry(
- request:
- | OpenAIClient.Chat.ChatCompletionCreateParamsStreaming
- | OpenAIClient.Chat.ChatCompletionCreateParamsNonStreaming,
- options?: OpenAICoreRequestOptions
- ): Promise<
- | AsyncIterable
- | OpenAIClient.Chat.Completions.ChatCompletion
- > {
- const requestOptions = this._getClientOptions(options);
- return this.caller.call(async () => {
- try {
- const res = await this.client.chat.completions.create(
- request,
- requestOptions
- );
- return res;
- } catch (e) {
- const error = wrapOpenAIClientError(e);
- throw error;
- }
- });
- }
-
- private _getClientOptions(options: OpenAICoreRequestOptions | undefined) {
- if (!this.client) {
- const openAIEndpointConfig: OpenAIEndpointConfig = {
- azureOpenAIApiDeploymentName: this.azureOpenAIApiDeploymentName,
- azureOpenAIApiInstanceName: this.azureOpenAIApiInstanceName,
- azureOpenAIApiKey: this.azureOpenAIApiKey,
- azureOpenAIBasePath: this.azureOpenAIBasePath,
- baseURL: this.clientConfig.baseURL,
- };
-
- const endpoint = getEndpoint(openAIEndpointConfig);
- const params = {
- ...this.clientConfig,
- baseURL: endpoint,
- timeout: this.timeout,
- maxRetries: 0,
- };
- if (!params.baseURL) {
- delete params.baseURL;
- }
-
- this.client = new OpenAIClient(params);
- }
- const requestOptions = {
- ...this.clientConfig,
- ...options,
- } as OpenAICoreRequestOptions;
- if (this.azureOpenAIApiKey) {
- requestOptions.headers = {
- "api-key": this.azureOpenAIApiKey,
- ...requestOptions.headers,
- };
- requestOptions.query = {
- "api-version": this.azureOpenAIApiVersion,
- ...requestOptions.query,
- };
- }
- return requestOptions;
- }
-
- _llmType() {
- return "openai";
- }
-
- /** @ignore */
- _combineLLMOutput(...llmOutputs: OpenAILLMOutput[]): OpenAILLMOutput {
- return llmOutputs.reduce<{
- [key in keyof OpenAILLMOutput]: Required;
- }>(
- (acc, llmOutput) => {
- if (llmOutput && llmOutput.tokenUsage) {
- acc.tokenUsage.completionTokens +=
- llmOutput.tokenUsage.completionTokens ?? 0;
- acc.tokenUsage.promptTokens += llmOutput.tokenUsage.promptTokens ?? 0;
- acc.tokenUsage.totalTokens += llmOutput.tokenUsage.totalTokens ?? 0;
- }
- return acc;
- },
- {
- tokenUsage: {
- completionTokens: 0,
- promptTokens: 0,
- totalTokens: 0,
- },
- }
- );
- }
-}
+export { type ChatOpenAICallOptions, ChatOpenAI };
export class PromptLayerChatOpenAI extends ChatOpenAI {
promptLayerApiKey?: string;
diff --git a/langchain/src/chat_models/portkey.ts b/langchain/src/chat_models/portkey.ts
index fd41231b9ac3..41b8ae09537c 100644
--- a/langchain/src/chat_models/portkey.ts
+++ b/langchain/src/chat_models/portkey.ts
@@ -1,182 +1 @@
-import { LLMOptions } from "portkey-ai";
-import { CallbackManagerForLLMRun } from "../callbacks/manager.js";
-import { PortkeySession, getPortkeySession } from "../llms/portkey.js";
-import {
- AIMessage,
- AIMessageChunk,
- BaseMessage,
- ChatGeneration,
- ChatGenerationChunk,
- ChatMessage,
- ChatMessageChunk,
- ChatResult,
- FunctionMessageChunk,
- HumanMessage,
- HumanMessageChunk,
- SystemMessage,
- SystemMessageChunk,
-} from "../schema/index.js";
-import { BaseChatModel } from "./base.js";
-
-interface Message {
- role?: string;
- content?: string;
-}
-
-function portkeyResponseToChatMessage(message: Message): BaseMessage {
- switch (message.role) {
- case "user":
- return new HumanMessage(message.content || "");
- case "assistant":
- return new AIMessage(message.content || "");
- case "system":
- return new SystemMessage(message.content || "");
- default:
- return new ChatMessage(message.content || "", message.role ?? "unknown");
- }
-}
-
-function _convertDeltaToMessageChunk(
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- delta: Record
-) {
- const { role } = delta;
- const content = delta.content ?? "";
- let additional_kwargs;
- if (delta.function_call) {
- additional_kwargs = {
- function_call: delta.function_call,
- };
- } else {
- additional_kwargs = {};
- }
- if (role === "user") {
- return new HumanMessageChunk({ content });
- } else if (role === "assistant") {
- return new AIMessageChunk({ content, additional_kwargs });
- } else if (role === "system") {
- return new SystemMessageChunk({ content });
- } else if (role === "function") {
- return new FunctionMessageChunk({
- content,
- additional_kwargs,
- name: delta.name,
- });
- } else {
- return new ChatMessageChunk({ content, role });
- }
-}
-
-export class PortkeyChat extends BaseChatModel {
- apiKey?: string = undefined;
-
- baseURL?: string = undefined;
-
- mode?: string = undefined;
-
- llms?: [LLMOptions] | null = undefined;
-
- session: PortkeySession;
-
- constructor(init?: Partial) {
- super(init ?? {});
- this.apiKey = init?.apiKey;
- this.baseURL = init?.baseURL;
- this.mode = init?.mode;
- this.llms = init?.llms;
- this.session = getPortkeySession({
- apiKey: this.apiKey,
- baseURL: this.baseURL,
- llms: this.llms,
- mode: this.mode,
- });
- }
-
- _llmType() {
- return "portkey";
- }
-
- async _generate(
- messages: BaseMessage[],
- options: this["ParsedCallOptions"],
- _?: CallbackManagerForLLMRun
- ): Promise {
- const messagesList = messages.map((message) => {
- if (typeof message.content !== "string") {
- throw new Error(
- "PortkeyChat does not support non-string message content."
- );
- }
- return {
- role: message._getType() as string,
- content: message.content,
- };
- });
- const response = await this.session.portkey.chatCompletions.create({
- messages: messagesList,
- ...options,
- stream: false,
- });
- const generations: ChatGeneration[] = [];
- for (const data of response.choices ?? []) {
- const text = data.message?.content ?? "";
- const generation: ChatGeneration = {
- text,
- message: portkeyResponseToChatMessage(data.message ?? {}),
- };
- if (data.finish_reason) {
- generation.generationInfo = { finish_reason: data.finish_reason };
- }
- generations.push(generation);
- }
-
- return {
- generations,
- };
- }
-
- async *_streamResponseChunks(
- messages: BaseMessage[],
- options: this["ParsedCallOptions"],
- runManager?: CallbackManagerForLLMRun
- ): AsyncGenerator {
- const messagesList = messages.map((message) => {
- if (typeof message.content !== "string") {
- throw new Error(
- "PortkeyChat does not support non-string message content."
- );
- }
- return {
- role: message._getType() as string,
- content: message.content,
- };
- });
- const response = await this.session.portkey.chatCompletions.create({
- messages: messagesList,
- ...options,
- stream: true,
- });
- for await (const data of response) {
- const choice = data?.choices[0];
- if (!choice) {
- continue;
- }
- const chunk = new ChatGenerationChunk({
- message: _convertDeltaToMessageChunk(choice.delta ?? {}),
- text: choice.message?.content ?? "",
- generationInfo: {
- finishReason: choice.finish_reason,
- },
- });
- yield chunk;
- void runManager?.handleLLMNewToken(chunk.text ?? "");
- }
- if (options.signal?.aborted) {
- throw new Error("AbortError");
- }
- }
-
- _combineLLMOutput() {
- return {};
- }
-}
+export * from "@langchain/community/chat_models/portkey";
diff --git a/langchain/src/chat_models/yandex.ts b/langchain/src/chat_models/yandex.ts
index 5365183792ca..3dbac8ffb540 100644
--- a/langchain/src/chat_models/yandex.ts
+++ b/langchain/src/chat_models/yandex.ts
@@ -1,142 +1 @@
-import { CallbackManagerForLLMRun } from "../callbacks/manager.js";
-import { YandexGPTInputs } from "../llms/yandex.js";
-import {
- AIMessage,
- BaseMessage,
- ChatResult,
- ChatGeneration,
-} from "../schema/index.js";
-import { getEnvironmentVariable } from "../util/env.js";
-import { BaseChatModel } from "./base.js";
-
-const apiUrl = "https://llm.api.cloud.yandex.net/llm/v1alpha/chat";
-
-interface ParsedMessage {
- role: string;
- text: string;
-}
-
-function _parseChatHistory(history: BaseMessage[]): [ParsedMessage[], string] {
- const chatHistory: ParsedMessage[] = [];
- let instruction = "";
-
- for (const message of history) {
- if (typeof message.content !== "string") {
- throw new Error(
- "ChatYandexGPT does not support non-string message content."
- );
- }
- if ("content" in message) {
- if (message._getType() === "human") {
- chatHistory.push({ role: "user", text: message.content });
- } else if (message._getType() === "ai") {
- chatHistory.push({ role: "assistant", text: message.content });
- } else if (message._getType() === "system") {
- instruction = message.content;
- }
- }
- }
-
- return [chatHistory, instruction];
-}
-
-/**
- * @example
- * ```typescript
- * const chat = new ChatYandexGPT({});
- * // The assistant is set to translate English to French.
- * const res = await chat.call([
- * new SystemMessage(
- * "You are a helpful assistant that translates English to French."
- * ),
- * new HumanMessage("I love programming."),
- * ]);
- * console.log(res);
- * ```
- */
-export class ChatYandexGPT extends BaseChatModel {
- apiKey?: string;
-
- iamToken?: string;
-
- temperature = 0.6;
-
- maxTokens = 1700;
-
- model = "general";
-
- constructor(fields?: YandexGPTInputs) {
- super(fields ?? {});
-
- const apiKey = fields?.apiKey ?? getEnvironmentVariable("YC_API_KEY");
-
- const iamToken = fields?.iamToken ?? getEnvironmentVariable("YC_IAM_TOKEN");
-
- if (apiKey === undefined && iamToken === undefined) {
- throw new Error(
- "Please set the YC_API_KEY or YC_IAM_TOKEN environment variable or pass it to the constructor as the apiKey or iamToken field."
- );
- }
-
- this.apiKey = apiKey;
- this.iamToken = iamToken;
- this.maxTokens = fields?.maxTokens ?? this.maxTokens;
- this.temperature = fields?.temperature ?? this.temperature;
- this.model = fields?.model ?? this.model;
- }
-
- _llmType() {
- return "yandexgpt";
- }
-
- _combineLLMOutput?() {
- return {};
- }
-
- /** @ignore */
- async _generate(
- messages: BaseMessage[],
- options: this["ParsedCallOptions"],
- _?: CallbackManagerForLLMRun | undefined
- ): Promise {
- const [messageHistory, instruction] = _parseChatHistory(messages);
- const headers = { "Content-Type": "application/json", Authorization: "" };
- if (this.apiKey !== undefined) {
- headers.Authorization = `Api-Key ${this.apiKey}`;
- } else {
- headers.Authorization = `Bearer ${this.iamToken}`;
- }
- const bodyData = {
- model: this.model,
- generationOptions: {
- temperature: this.temperature,
- maxTokens: this.maxTokens,
- },
- messages: messageHistory,
- instructionText: instruction,
- };
- const response = await fetch(apiUrl, {
- method: "POST",
- headers,
- body: JSON.stringify(bodyData),
- signal: options?.signal,
- });
- if (!response.ok) {
- throw new Error(
- `Failed to fetch ${apiUrl} from YandexGPT: ${response.status}`
- );
- }
- const responseData = await response.json();
- const { result } = responseData;
- const { text } = result.message;
- const totalTokens = result.num_tokens;
- const generations: ChatGeneration[] = [
- { text, message: new AIMessage(text) },
- ];
-
- return {
- generations,
- llmOutput: { totalTokens },
- };
- }
-}
+export * from "@langchain/community/chat_models/yandex";
diff --git a/langchain/src/document_loaders/fs/openai_whisper_audio.ts b/langchain/src/document_loaders/fs/openai_whisper_audio.ts
index fbbdbef6f25b..468eba28c1e5 100644
--- a/langchain/src/document_loaders/fs/openai_whisper_audio.ts
+++ b/langchain/src/document_loaders/fs/openai_whisper_audio.ts
@@ -1,4 +1,4 @@
-import { type ClientOptions, OpenAI as OpenAIClient, toFile } from "openai";
+import { type ClientOptions, OpenAIClient, toFile } from "@langchain/openai";
import { Document } from "../../document.js";
import { BufferLoader } from "./buffer.js";
diff --git a/langchain/src/document_transformers/html_to_text.ts b/langchain/src/document_transformers/html_to_text.ts
index 987d1c6feed3..a3d4023dfdd0 100644
--- a/langchain/src/document_transformers/html_to_text.ts
+++ b/langchain/src/document_transformers/html_to_text.ts
@@ -1,43 +1 @@
-import { htmlToText } from "html-to-text";
-import type { HtmlToTextOptions } from "html-to-text";
-import { Document } from "../document.js";
-import { MappingDocumentTransformer } from "../schema/document.js";
-
-/**
- * A transformer that converts HTML content to plain text.
- * @example
- * ```typescript
- * const loader = new CheerioWebBaseLoader("https://example.com/some-page");
- * const docs = await loader.load();
- *
- * const splitter = new RecursiveCharacterTextSplitter({
- * maxCharacterCount: 1000,
- * });
- * const transformer = new HtmlToTextTransformer();
- *
- * // The sequence of text splitting followed by HTML to text transformation
- * const sequence = splitter.pipe(transformer);
- *
- * // Processing the loaded documents through the sequence
- * const newDocuments = await sequence.invoke(docs);
- *
- * console.log(newDocuments);
- * ```
- */
-export class HtmlToTextTransformer extends MappingDocumentTransformer {
- static lc_name() {
- return "HtmlToTextTransformer";
- }
-
- constructor(protected options: HtmlToTextOptions = {}) {
- super(options);
- }
-
- async _transformDocument(document: Document): Promise {
- const extractedContent = htmlToText(document.pageContent, this.options);
- return new Document({
- pageContent: extractedContent,
- metadata: { ...document.metadata },
- });
- }
-}
+export * from "@langchain/community/document_transformers/html_to_text";
diff --git a/langchain/src/document_transformers/mozilla_readability.ts b/langchain/src/document_transformers/mozilla_readability.ts
index 1eb302bbbc38..481f786c13d0 100644
--- a/langchain/src/document_transformers/mozilla_readability.ts
+++ b/langchain/src/document_transformers/mozilla_readability.ts
@@ -1,52 +1 @@
-import { Readability } from "@mozilla/readability";
-import { JSDOM } from "jsdom";
-import { Options } from "mozilla-readability";
-import { Document } from "../document.js";
-import { MappingDocumentTransformer } from "../schema/document.js";
-
-/**
- * A transformer that uses the Mozilla Readability library to extract the
- * main content from a web page.
- * @example
- * ```typescript
- * const loader = new CheerioWebBaseLoader("https://example.com/article");
- * const docs = await loader.load();
- *
- * const splitter = new RecursiveCharacterTextSplitter({
- * maxCharacterCount: 5000,
- * });
- * const transformer = new MozillaReadabilityTransformer();
- *
- * // The sequence processes the loaded documents through the splitter and then the transformer.
- * const sequence = splitter.pipe(transformer);
- *
- * // Invoke the sequence to transform the documents into a more readable format.
- * const newDocuments = await sequence.invoke(docs);
- *
- * console.log(newDocuments);
- * ```
- */
-export class MozillaReadabilityTransformer extends MappingDocumentTransformer {
- static lc_name() {
- return "MozillaReadabilityTransformer";
- }
-
- constructor(protected options: Options = {}) {
- super(options);
- }
-
- async _transformDocument(document: Document): Promise {
- const doc = new JSDOM(document.pageContent);
-
- const readability = new Readability(doc.window.document, this.options);
-
- const result = readability.parse();
-
- return new Document({
- pageContent: result?.textContent ?? "",
- metadata: {
- ...document.metadata,
- },
- });
- }
-}
+export * from "@langchain/community/document_transformers/mozilla_readability";
diff --git a/langchain/src/embeddings/bedrock.ts b/langchain/src/embeddings/bedrock.ts
index f9ca960f3a1a..0158430fd0a5 100644
--- a/langchain/src/embeddings/bedrock.ts
+++ b/langchain/src/embeddings/bedrock.ts
@@ -1,142 +1 @@
-import {
- BedrockRuntimeClient,
- InvokeModelCommand,
-} from "@aws-sdk/client-bedrock-runtime";
-import { Embeddings, EmbeddingsParams } from "./base.js";
-import type { CredentialType } from "../util/bedrock.js";
-
-/**
- * Interface that extends EmbeddingsParams and defines additional
- * parameters specific to the BedrockEmbeddings class.
- */
-export interface BedrockEmbeddingsParams extends EmbeddingsParams {
- /**
- * Model Name to use. Defaults to `amazon.titan-embed-text-v1` if not provided
- *
- */
- model?: string;
-
- /**
- * A client provided by the user that allows them to customze any
- * SDK configuration options.
- */
- client?: BedrockRuntimeClient;
-
- region?: string;
-
- credentials?: CredentialType;
-}
-
-/**
- * Class that extends the Embeddings class and provides methods for
- * generating embeddings using the Bedrock API.
- * @example
- * ```typescript
- * const embeddings = new BedrockEmbeddings({
- * region: "your-aws-region",
- * credentials: {
- * accessKeyId: "your-access-key-id",
- * secretAccessKey: "your-secret-access-key",
- * },
- * model: "amazon.titan-embed-text-v1",
- * });
- *
- * // Embed a query and log the result
- * const res = await embeddings.embedQuery(
- * "What would be a good company name for a company that makes colorful socks?"
- * );
- * console.log({ res });
- * ```
- */
-export class BedrockEmbeddings
- extends Embeddings
- implements BedrockEmbeddingsParams
-{
- model: string;
-
- client: BedrockRuntimeClient;
-
- batchSize = 512;
-
- constructor(fields?: BedrockEmbeddingsParams) {
- super(fields ?? {});
-
- this.model = fields?.model ?? "amazon.titan-embed-text-v1";
-
- this.client =
- fields?.client ??
- new BedrockRuntimeClient({
- region: fields?.region,
- credentials: fields?.credentials,
- });
- }
-
- /**
- * Protected method to make a request to the Bedrock API to generate
- * embeddings. Handles the retry logic and returns the response from the
- * API.
- * @param request Request to send to the Bedrock API.
- * @returns Promise that resolves to the response from the API.
- */
- protected async _embedText(text: string): Promise {
- return this.caller.call(async () => {
- try {
- // replace newlines, which can negatively affect performance.
- const cleanedText = text.replace(/\n/g, " ");
-
- const res = await this.client.send(
- new InvokeModelCommand({
- modelId: this.model,
- body: JSON.stringify({
- inputText: cleanedText,
- }),
- contentType: "application/json",
- accept: "application/json",
- })
- );
-
- const body = new TextDecoder().decode(res.body);
- return JSON.parse(body).embedding;
- } catch (e) {
- console.error({
- error: e,
- });
- // eslint-disable-next-line no-instanceof/no-instanceof
- if (e instanceof Error) {
- throw new Error(
- `An error occurred while embedding documents with Bedrock: ${e.message}`
- );
- }
-
- throw new Error(
- "An error occurred while embedding documents with Bedrock"
- );
- }
- });
- }
-
- /**
- * Method that takes a document as input and returns a promise that
- * resolves to an embedding for the document. It calls the _embedText
- * method with the document as the input.
- * @param document Document for which to generate an embedding.
- * @returns Promise that resolves to an embedding for the input document.
- */
- embedQuery(document: string): Promise {
- return this.caller.callWithOptions(
- {},
- this._embedText.bind(this),
- document
- );
- }
-
- /**
- * Method to generate embeddings for an array of texts. Calls _embedText
- * method which batches and handles retry logic when calling the AWS Bedrock API.
- * @param documents Array of texts for which to generate embeddings.
- * @returns Promise that resolves to a 2D array of embeddings for each input document.
- */
- async embedDocuments(documents: string[]): Promise {
- return Promise.all(documents.map((document) => this._embedText(document)));
- }
-}
+export * from "@langchain/community/embeddings/bedrock";
diff --git a/langchain/src/embeddings/cloudflare_workersai.ts b/langchain/src/embeddings/cloudflare_workersai.ts
index 191213dfbf5f..b5d4cd6238a8 100644
--- a/langchain/src/embeddings/cloudflare_workersai.ts
+++ b/langchain/src/embeddings/cloudflare_workersai.ts
@@ -1,94 +1 @@
-import { Ai } from "@cloudflare/ai";
-import { Fetcher } from "@cloudflare/workers-types";
-import { chunkArray } from "../util/chunk.js";
-import { Embeddings, EmbeddingsParams } from "./base.js";
-
-type AiTextEmbeddingsInput = {
- text: string | string[];
-};
-
-type AiTextEmbeddingsOutput = {
- shape: number[];
- data: number[][];
-};
-
-export interface CloudflareWorkersAIEmbeddingsParams extends EmbeddingsParams {
- /** Binding */
- binding: Fetcher;
-
- /** Model name to use */
- modelName?: string;
-
- /**
- * The maximum number of documents to embed in a single request.
- */
- batchSize?: number;
-
- /**
- * Whether to strip new lines from the input text. This is recommended by
- * OpenAI, but may not be suitable for all use cases.
- */
- stripNewLines?: boolean;
-}
-
-export class CloudflareWorkersAIEmbeddings extends Embeddings {
- modelName = "@cf/baai/bge-base-en-v1.5";
-
- batchSize = 50;
-
- stripNewLines = true;
-
- ai: Ai;
-
- constructor(fields: CloudflareWorkersAIEmbeddingsParams) {
- super(fields);
-
- if (!fields.binding) {
- throw new Error(
- "Must supply a Workers AI binding, eg { binding: env.AI }"
- );
- }
- this.ai = new Ai(fields.binding);
- this.modelName = fields.modelName ?? this.modelName;
- this.stripNewLines = fields.stripNewLines ?? this.stripNewLines;
- }
-
- 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) => this.runEmbedding(batch));
- const batchResponses = await Promise.all(batchRequests);
- const embeddings: number[][] = [];
-
- for (let i = 0; i < batchResponses.length; i += 1) {
- const batchResponse = batchResponses[i];
- for (let j = 0; j < batchResponse.length; j += 1) {
- embeddings.push(batchResponse[j]);
- }
- }
-
- return embeddings;
- }
-
- async embedQuery(text: string): Promise {
- const data = await this.runEmbedding([
- this.stripNewLines ? text.replace(/\n/g, " ") : text,
- ]);
- return data[0];
- }
-
- private async runEmbedding(texts: string[]) {
- return this.caller.call(async () => {
- const response: AiTextEmbeddingsOutput = await this.ai.run(
- this.modelName,
- {
- text: texts,
- } as AiTextEmbeddingsInput
- );
- return response.data;
- });
- }
-}
+export * from "@langchain/community/embeddings/cloudflare_workersai";
diff --git a/langchain/src/embeddings/cohere.ts b/langchain/src/embeddings/cohere.ts
index 4d510c205459..83eb358d4e37 100644
--- a/langchain/src/embeddings/cohere.ts
+++ b/langchain/src/embeddings/cohere.ts
@@ -1,155 +1 @@
-import { chunkArray } from "../util/chunk.js";
-import { getEnvironmentVariable } from "../util/env.js";
-import { Embeddings, EmbeddingsParams } from "./base.js";
-
-/**
- * Interface that extends EmbeddingsParams and defines additional
- * parameters specific to the CohereEmbeddings class.
- */
-export interface CohereEmbeddingsParams extends EmbeddingsParams {
- modelName: string;
-
- /**
- * The maximum number of documents to embed in a single request. This is
- * limited by the Cohere API to a maximum of 96.
- */
- batchSize?: number;
-}
-
-/**
- * A class for generating embeddings using the Cohere API.
- * @example
- * ```typescript
- * // Embed a query using the CohereEmbeddings class
- * const model = new ChatOpenAI();
- * const res = await model.embedQuery(
- * "What would be a good company name for a company that makes colorful socks?",
- * );
- * console.log({ res });
- *
- * ```
- */
-export class CohereEmbeddings
- extends Embeddings
- implements CohereEmbeddingsParams
-{
- modelName = "small";
-
- batchSize = 48;
-
- private apiKey: string;
-
- private client: typeof import("cohere-ai");
-
- /**
- * Constructor for the CohereEmbeddings class.
- * @param fields - An optional object with properties to configure the instance.
- */
- constructor(
- fields?: Partial & {
- verbose?: boolean;
- apiKey?: string;
- }
- ) {
- const fieldsWithDefaults = { maxConcurrency: 2, ...fields };
-
- super(fieldsWithDefaults);
-
- const apiKey =
- fieldsWithDefaults?.apiKey || getEnvironmentVariable("COHERE_API_KEY");
-
- if (!apiKey) {
- throw new Error("Cohere API key not found");
- }
-
- this.modelName = fieldsWithDefaults?.modelName ?? this.modelName;
- this.batchSize = fieldsWithDefaults?.batchSize ?? this.batchSize;
- this.apiKey = apiKey;
- }
-
- /**
- * Generates embeddings for an array of texts.
- * @param texts - An array of strings to generate embeddings for.
- * @returns A Promise that resolves to an array of embeddings.
- */
- async embedDocuments(texts: string[]): Promise {
- await this.maybeInitClient();
-
- const batches = chunkArray(texts, this.batchSize);
-
- const batchRequests = batches.map((batch) =>
- this.embeddingWithRetry({
- model: this.modelName,
- texts: batch,
- })
- );
-
- const batchResponses = await Promise.all(batchRequests);
-
- const embeddings: number[][] = [];
-
- for (let i = 0; i < batchResponses.length; i += 1) {
- const batch = batches[i];
- const { body: batchResponse } = batchResponses[i];
- for (let j = 0; j < batch.length; j += 1) {
- embeddings.push(batchResponse.embeddings[j]);
- }
- }
-
- return embeddings;
- }
-
- /**
- * Generates an embedding for a single text.
- * @param text - A string to generate an embedding for.
- * @returns A Promise that resolves to an array of numbers representing the embedding.
- */
- async embedQuery(text: string): Promise {
- await this.maybeInitClient();
-
- const { body } = await this.embeddingWithRetry({
- model: this.modelName,
- texts: [text],
- });
- return body.embeddings[0];
- }
-
- /**
- * Generates embeddings with retry capabilities.
- * @param request - An object containing the request parameters for generating embeddings.
- * @returns A Promise that resolves to the API response.
- */
- private async embeddingWithRetry(
- request: Parameters[0]
- ) {
- await this.maybeInitClient();
-
- return this.caller.call(this.client.embed.bind(this.client), request);
- }
-
- /**
- * Initializes the Cohere client if it hasn't been initialized already.
- */
- private async maybeInitClient() {
- if (!this.client) {
- const { cohere } = await CohereEmbeddings.imports();
-
- this.client = cohere;
- this.client.init(this.apiKey);
- }
- }
-
- /** @ignore */
- static async imports(): Promise<{
- cohere: typeof import("cohere-ai");
- }> {
- try {
- const { default: cohere } = await import("cohere-ai");
- return { cohere };
- } catch (e) {
- throw new Error(
- "Please install cohere-ai as a dependency with, e.g. `yarn add cohere-ai`"
- );
- }
- }
-}
+export * from "@langchain/community/embeddings/cohere";
diff --git a/langchain/src/embeddings/googlepalm.ts b/langchain/src/embeddings/googlepalm.ts
index 2d969dc98106..950bc455c2c6 100644
--- a/langchain/src/embeddings/googlepalm.ts
+++ b/langchain/src/embeddings/googlepalm.ts
@@ -1,107 +1 @@
-import { TextServiceClient } from "@google-ai/generativelanguage";
-import { GoogleAuth } from "google-auth-library";
-import { Embeddings, EmbeddingsParams } from "./base.js";
-import { getEnvironmentVariable } from "../util/env.js";
-
-/**
- * Interface that extends EmbeddingsParams and defines additional
- * parameters specific to the GooglePaLMEmbeddings class.
- */
-export interface GooglePaLMEmbeddingsParams extends EmbeddingsParams {
- /**
- * Model Name to use
- *
- * Note: The format must follow the pattern - `models/{model}`
- */
- modelName?: string;
- /**
- * Google Palm API key to use
- */
- apiKey?: string;
-}
-
-/**
- * Class that extends the Embeddings class and provides methods for
- * generating embeddings using the Google Palm API.
- * @example
- * ```typescript
- * const model = new GooglePaLMEmbeddings({
- * apiKey: "",
- * modelName: "models/embedding-gecko-001",
- * });
- *
- * // Embed a single query
- * const res = await model.embedQuery(
- * "What would be a good company name for a company that makes colorful socks?"
- * );
- * console.log({ res });
- *
- * // Embed multiple documents
- * const documentRes = await model.embedDocuments(["Hello world", "Bye bye"]);
- * console.log({ documentRes });
- * ```
- */
-export class GooglePaLMEmbeddings
- extends Embeddings
- implements GooglePaLMEmbeddingsParams
-{
- apiKey?: string;
-
- modelName = "models/embedding-gecko-001";
-
- private client: TextServiceClient;
-
- constructor(fields?: GooglePaLMEmbeddingsParams) {
- super(fields ?? {});
-
- this.modelName = fields?.modelName ?? this.modelName;
-
- this.apiKey =
- fields?.apiKey ?? getEnvironmentVariable("GOOGLE_PALM_API_KEY");
- if (!this.apiKey) {
- throw new Error(
- "Please set an API key for Google Palm 2 in the environment variable GOOGLE_PALM_API_KEY or in the `apiKey` field of the GooglePalm constructor"
- );
- }
-
- this.client = new TextServiceClient({
- authClient: new GoogleAuth().fromAPIKey(this.apiKey),
- });
- }
-
- protected async _embedText(text: string): Promise {
- // replace newlines, which can negatively affect performance.
- const cleanedText = text.replace(/\n/g, " ");
- const res = await this.client.embedText({
- model: this.modelName,
- text: cleanedText,
- });
- return res[0].embedding?.value ?? [];
- }
-
- /**
- * Method that takes a document as input and returns a promise that
- * resolves to an embedding for the document. It calls the _embedText
- * method with the document as the input.
- * @param document Document for which to generate an embedding.
- * @returns Promise that resolves to an embedding for the input document.
- */
- embedQuery(document: string): Promise {
- return this.caller.callWithOptions(
- {},
- this._embedText.bind(this),
- document
- );
- }
-
- /**
- * Method that takes an array of documents as input and returns a promise
- * that resolves to a 2D array of embeddings for each document. It calls
- * the _embedText method for each document in the array.
- * @param documents Array of documents for which to generate embeddings.
- * @returns Promise that resolves to a 2D array of embeddings for each input document.
- */
- embedDocuments(documents: string[]): Promise {
- return Promise.all(documents.map((document) => this._embedText(document)));
- }
-}
+export * from "@langchain/community/embeddings/googlepalm";
diff --git a/langchain/src/embeddings/googlevertexai.ts b/langchain/src/embeddings/googlevertexai.ts
index 121d8c6efd9b..3eded4165344 100644
--- a/langchain/src/embeddings/googlevertexai.ts
+++ b/langchain/src/embeddings/googlevertexai.ts
@@ -1,145 +1 @@
-import { GoogleAuth, GoogleAuthOptions } from "google-auth-library";
-import { Embeddings, EmbeddingsParams } from "./base.js";
-import {
- GoogleVertexAIBasePrediction,
- GoogleVertexAIBaseLLMInput,
- GoogleVertexAILLMPredictions,
-} from "../types/googlevertexai-types.js";
-import { GoogleVertexAILLMConnection } from "../util/googlevertexai-connection.js";
-import { AsyncCallerCallOptions } from "../util/async_caller.js";
-import { chunkArray } from "../util/chunk.js";
-
-/**
- * Defines the parameters required to initialize a
- * GoogleVertexAIEmbeddings instance. It extends EmbeddingsParams and
- * GoogleVertexAIConnectionParams.
- */
-export interface GoogleVertexAIEmbeddingsParams
- extends EmbeddingsParams,
- GoogleVertexAIBaseLLMInput {}
-
-/**
- * Defines additional options specific to the
- * GoogleVertexAILLMEmbeddingsInstance. It extends AsyncCallerCallOptions.
- */
-interface GoogleVertexAILLMEmbeddingsOptions extends AsyncCallerCallOptions {}
-
-/**
- * Represents an instance for generating embeddings using the Google
- * Vertex AI API. It contains the content to be embedded.
- */
-interface GoogleVertexAILLMEmbeddingsInstance {
- content: string;
-}
-
-/**
- * Defines the structure of the embeddings results returned by the Google
- * Vertex AI API. It extends GoogleVertexAIBasePrediction and contains the
- * embeddings and their statistics.
- */
-interface GoogleVertexEmbeddingsResults extends GoogleVertexAIBasePrediction {
- embeddings: {
- statistics: {
- token_count: number;
- truncated: boolean;
- };
- values: number[];
- };
-}
-
-/**
- * Enables calls to the Google Cloud's Vertex AI API to access
- * the embeddings generated by Large Language Models.
- *
- * To use, you will need to have one of the following authentication
- * methods in place:
- * - You are logged into an account permitted to the Google Cloud project
- * using Vertex AI.
- * - You are running this on a machine using a service account permitted to
- * the Google Cloud project using Vertex AI.
- * - The `GOOGLE_APPLICATION_CREDENTIALS` environment variable is set to the
- * path of a credentials file for a service account permitted to the
- * Google Cloud project using Vertex AI.
- * @example
- * ```typescript
- * const model = new GoogleVertexAIEmbeddings();
- * const res = await model.embedQuery(
- * "What would be a good company name for a company that makes colorful socks?"
- * );
- * console.log({ res });
- * ```
- */
-export class GoogleVertexAIEmbeddings
- extends Embeddings
- implements GoogleVertexAIEmbeddingsParams
-{
- model = "textembedding-gecko";
-
- private connection: GoogleVertexAILLMConnection<
- GoogleVertexAILLMEmbeddingsOptions,
- GoogleVertexAILLMEmbeddingsInstance,
- GoogleVertexEmbeddingsResults,
- GoogleAuthOptions
- >;
-
- constructor(fields?: GoogleVertexAIEmbeddingsParams) {
- super(fields ?? {});
-
- this.model = fields?.model ?? this.model;
-
- this.connection = new GoogleVertexAILLMConnection(
- { ...fields, ...this },
- this.caller,
- new GoogleAuth({
- scopes: "https://www.googleapis.com/auth/cloud-platform",
- ...fields?.authOptions,
- })
- );
- }
-
- /**
- * Takes an array of documents as input and returns a promise that
- * resolves to a 2D array of embeddings for each document. It splits the
- * documents into chunks and makes requests to the Google Vertex AI API to
- * generate embeddings.
- * @param documents An array of documents to be embedded.
- * @returns A promise that resolves to a 2D array of embeddings for each document.
- */
- async embedDocuments(documents: string[]): Promise {
- const instanceChunks: GoogleVertexAILLMEmbeddingsInstance[][] = chunkArray(
- documents.map((document) => ({
- content: document,
- })),
- 5
- ); // Vertex AI accepts max 5 instances per prediction
- const parameters = {};
- const options = {};
- const responses = await Promise.all(
- instanceChunks.map((instances) =>
- this.connection.request(instances, parameters, options)
- )
- );
- const result: number[][] =
- responses
- ?.map(
- (response) =>
- (
- response?.data as GoogleVertexAILLMPredictions
- )?.predictions?.map((result) => result.embeddings.values) ?? []
- )
- .flat() ?? [];
- return result;
- }
-
- /**
- * Takes a document as input and returns a promise that resolves to an
- * embedding for the document. It calls the embedDocuments method with the
- * document as the input.
- * @param document A document to be embedded.
- * @returns A promise that resolves to an embedding for the document.
- */
- async embedQuery(document: string): Promise {
- const data = await this.embedDocuments([document]);
- return data[0];
- }
-}
+export * from "@langchain/community/embeddings/googlevertexai";
diff --git a/langchain/src/embeddings/gradient_ai.ts b/langchain/src/embeddings/gradient_ai.ts
index e03b7a364c0f..83b02683d3d9 100644
--- a/langchain/src/embeddings/gradient_ai.ts
+++ b/langchain/src/embeddings/gradient_ai.ts
@@ -1,118 +1 @@
-import { Gradient } from "@gradientai/nodejs-sdk";
-import { getEnvironmentVariable } from "../util/env.js";
-import { chunkArray } from "../util/chunk.js";
-import { Embeddings, EmbeddingsParams } from "./base.js";
-
-/**
- * Interface for GradientEmbeddings parameters. Extends EmbeddingsParams and
- * defines additional parameters specific to the GradientEmbeddings class.
- */
-export interface GradientEmbeddingsParams extends EmbeddingsParams {
- /**
- * Gradient AI Access Token.
- * Provide Access Token if you do not wish to automatically pull from env.
- */
- gradientAccessKey?: string;
- /**
- * Gradient Workspace Id.
- * Provide workspace id if you do not wish to automatically pull from env.
- */
- workspaceId?: string;
-}
-
-/**
- * Class for generating embeddings using the Gradient AI's API. Extends the
- * Embeddings class and implements GradientEmbeddingsParams and
- */
-export class GradientEmbeddings
- extends Embeddings
- implements GradientEmbeddingsParams
-{
- gradientAccessKey?: string;
-
- workspaceId?: string;
-
- batchSize = 128;
-
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- model: any;
-
- constructor(fields: GradientEmbeddingsParams) {
- super(fields);
-
- this.gradientAccessKey =
- fields?.gradientAccessKey ??
- getEnvironmentVariable("GRADIENT_ACCESS_TOKEN");
- this.workspaceId =
- fields?.workspaceId ?? getEnvironmentVariable("GRADIENT_WORKSPACE_ID");
-
- if (!this.gradientAccessKey) {
- throw new Error("Missing Gradient AI Access Token");
- }
-
- if (!this.workspaceId) {
- throw new Error("Missing Gradient AI Workspace ID");
- }
- }
-
- /**
- * Method to generate embeddings for an array of documents. Splits the
- * documents into batches and makes requests to the Gradient 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 {
- await this.setModel();
-
- const mappedTexts = texts.map((text) => ({ input: text }));
-
- const batches = chunkArray(mappedTexts, this.batchSize);
-
- const batchRequests = batches.map((batch) =>
- this.caller.call(async () =>
- this.model.generateEmbeddings({
- inputs: batch,
- })
- )
- );
- const batchResponses = await Promise.all(batchRequests);
-
- const embeddings: number[][] = [];
- for (let i = 0; i < batchResponses.length; i += 1) {
- const batch = batches[i];
- const { embeddings: batchResponse } = batchResponses[i];
- for (let j = 0; j < batch.length; j += 1) {
- embeddings.push(batchResponse[j].embedding);
- }
- }
- return embeddings;
- }
-
- /**
- * Method to generate an embedding for a single document. Calls the
- * embedDocuments 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 data = await this.embedDocuments([text]);
- return data[0];
- }
-
- /**
- * Method to set the model to use for generating embeddings.
- * @sets the class' `model` value to that of the retrieved Embeddings Model.
- */
- async setModel() {
- if (this.model) return;
-
- const gradient = new Gradient({
- accessToken: this.gradientAccessKey,
- workspaceId: this.workspaceId,
- });
- this.model = await gradient.getEmbeddingsModel({
- slug: "bge-large",
- });
- }
-}
+export * from "@langchain/community/embeddings/gradient_ai";
diff --git a/langchain/src/embeddings/hf.ts b/langchain/src/embeddings/hf.ts
index 83b801a90566..7042535179ed 100644
--- a/langchain/src/embeddings/hf.ts
+++ b/langchain/src/embeddings/hf.ts
@@ -1,77 +1 @@
-import { HfInference, HfInferenceEndpoint } from "@huggingface/inference";
-import { Embeddings, EmbeddingsParams } from "./base.js";
-import { getEnvironmentVariable } from "../util/env.js";
-
-/**
- * Interface that extends EmbeddingsParams and defines additional
- * parameters specific to the HuggingFaceInferenceEmbeddings class.
- */
-export interface HuggingFaceInferenceEmbeddingsParams extends EmbeddingsParams {
- apiKey?: string;
- model?: string;
- endpointUrl?: string;
-}
-
-/**
- * Class that extends the Embeddings class and provides methods for
- * generating embeddings using Hugging Face models through the
- * HuggingFaceInference API.
- */
-export class HuggingFaceInferenceEmbeddings
- extends Embeddings
- implements HuggingFaceInferenceEmbeddingsParams
-{
- apiKey?: string;
-
- model: string;
-
- endpointUrl?: string;
-
- client: HfInference | HfInferenceEndpoint;
-
- constructor(fields?: HuggingFaceInferenceEmbeddingsParams) {
- super(fields ?? {});
-
- this.model = fields?.model ?? "BAAI/bge-base-en-v1.5";
- this.apiKey =
- fields?.apiKey ?? getEnvironmentVariable("HUGGINGFACEHUB_API_KEY");
- this.endpointUrl = fields?.endpointUrl;
- this.client = this.endpointUrl
- ? new HfInference(this.apiKey).endpoint(this.endpointUrl)
- : new HfInference(this.apiKey);
- }
-
- async _embed(texts: string[]): Promise {
- // replace newlines, which can negatively affect performance.
- const clean = texts.map((text) => text.replace(/\n/g, " "));
- return this.caller.call(() =>
- this.client.featureExtraction({
- model: this.model,
- inputs: clean,
- })
- ) as Promise;
- }
-
- /**
- * Method that takes a document as input and returns a promise that
- * resolves to an embedding for the document. It calls the _embed method
- * with the document as the input and returns the first embedding in the
- * resulting array.
- * @param document Document to generate an embedding for.
- * @returns Promise that resolves to an embedding for the document.
- */
- embedQuery(document: string): Promise {
- return this._embed([document]).then((embeddings) => embeddings[0]);
- }
-
- /**
- * Method that takes an array of documents as input and returns a promise
- * that resolves to a 2D array of embeddings for each document. It calls
- * the _embed method with the documents as the input.
- * @param documents Array of documents to generate embeddings for.
- * @returns Promise that resolves to a 2D array of embeddings for each document.
- */
- embedDocuments(documents: string[]): Promise {
- return this._embed(documents);
- }
-}
+export * from "@langchain/community/embeddings/hf";
diff --git a/langchain/src/embeddings/hf_transformers.ts b/langchain/src/embeddings/hf_transformers.ts
index e2b8bdcc98a5..aff3ec98244e 100644
--- a/langchain/src/embeddings/hf_transformers.ts
+++ b/langchain/src/embeddings/hf_transformers.ts
@@ -1,105 +1 @@
-import { Pipeline, pipeline } from "@xenova/transformers";
-import { chunkArray } from "../util/chunk.js";
-import { Embeddings, EmbeddingsParams } from "./base.js";
-
-export interface HuggingFaceTransformersEmbeddingsParams
- extends EmbeddingsParams {
- /** Model name to use */
- modelName: string;
-
- /**
- * Timeout to use when making requests to OpenAI.
- */
- timeout?: number;
-
- /**
- * The maximum number of documents to embed in a single request.
- */
- batchSize?: number;
-
- /**
- * Whether to strip new lines from the input text. This is recommended by
- * OpenAI, but may not be suitable for all use cases.
- */
- stripNewLines?: boolean;
-}
-
-/**
- * @example
- * ```typescript
- * const model = new HuggingFaceTransformersEmbeddings({
- * modelName: "Xenova/all-MiniLM-L6-v2",
- * });
- *
- * // Embed a single query
- * const res = await model.embedQuery(
- * "What would be a good company name for a company that makes colorful socks?"
- * );
- * console.log({ res });
- *
- * // Embed multiple documents
- * const documentRes = await model.embedDocuments(["Hello world", "Bye bye"]);
- * console.log({ documentRes });
- * ```
- */
-export class HuggingFaceTransformersEmbeddings
- extends Embeddings
- implements HuggingFaceTransformersEmbeddingsParams
-{
- modelName = "Xenova/all-MiniLM-L6-v2";
-
- batchSize = 512;
-
- stripNewLines = true;
-
- timeout?: number;
-
- private pipelinePromise: Promise;
-
- constructor(fields?: Partial) {
- super(fields ?? {});
-
- this.modelName = fields?.modelName ?? this.modelName;
- this.stripNewLines = fields?.stripNewLines ?? this.stripNewLines;
- this.timeout = fields?.timeout;
- }
-
- 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) => this.runEmbedding(batch));
- const batchResponses = await Promise.all(batchRequests);
- const embeddings: number[][] = [];
-
- for (let i = 0; i < batchResponses.length; i += 1) {
- const batchResponse = batchResponses[i];
- for (let j = 0; j < batchResponse.length; j += 1) {
- embeddings.push(batchResponse[j]);
- }
- }
-
- return embeddings;
- }
-
- async embedQuery(text: string): Promise {
- const data = await this.runEmbedding([
- this.stripNewLines ? text.replace(/\n/g, " ") : text,
- ]);
- return data[0];
- }
-
- private async runEmbedding(texts: string[]) {
- const pipe = await (this.pipelinePromise ??= pipeline(
- "feature-extraction",
- this.modelName
- ));
-
- return this.caller.call(async () => {
- const output = await pipe(texts, { pooling: "mean", normalize: true });
- return output.tolist();
- });
- }
-}
+export * from "@langchain/community/embeddings/hf_transformers";
diff --git a/langchain/src/embeddings/llama_cpp.ts b/langchain/src/embeddings/llama_cpp.ts
index 51b9b3c3e007..3fcf55dda59a 100644
--- a/langchain/src/embeddings/llama_cpp.ts
+++ b/langchain/src/embeddings/llama_cpp.ts
@@ -1,103 +1 @@
-import { LlamaModel, LlamaContext } from "node-llama-cpp";
-import {
- LlamaBaseCppInputs,
- createLlamaModel,
- createLlamaContext,
-} from "../util/llama_cpp.js";
-import { Embeddings, EmbeddingsParams } from "./base.js";
-
-/**
- * Note that the modelPath is the only required parameter. For testing you
- * can set this in the environment variable `LLAMA_PATH`.
- */
-export interface LlamaCppEmbeddingsParams
- extends LlamaBaseCppInputs,
- EmbeddingsParams {}
-
-/**
- * @example
- * ```typescript
- * // Initialize LlamaCppEmbeddings with the path to the model file
- * const embeddings = new LlamaCppEmbeddings({
- * modelPath: "/Replace/with/path/to/your/model/gguf-llama2-q4_0.bin",
- * });
- *
- * // Embed a query string using the Llama embeddings
- * const res = embeddings.embedQuery("Hello Llama!");
- *
- * // Output the resulting embeddings
- * console.log(res);
- *
- * ```
- */
-export class LlamaCppEmbeddings extends Embeddings {
- _model: LlamaModel;
-
- _context: LlamaContext;
-
- constructor(inputs: LlamaCppEmbeddingsParams) {
- super(inputs);
- const _inputs = inputs;
- _inputs.embedding = true;
-
- this._model = createLlamaModel(_inputs);
- this._context = createLlamaContext(this._model, _inputs);
- }
-
- /**
- * Generates embeddings for an array of texts.
- * @param texts - An array of strings to generate embeddings for.
- * @returns A Promise that resolves to an array of embeddings.
- */
- async embedDocuments(texts: string[]): Promise {
- const tokensArray = [];
-
- for (const text of texts) {
- const encodings = await this.caller.call(
- () =>
- new Promise((resolve) => {
- resolve(this._context.encode(text));
- })
- );
- tokensArray.push(encodings);
- }
-
- const embeddings: number[][] = [];
-
- for (const tokens of tokensArray) {
- const embedArray: number[] = [];
-
- for (let i = 0; i < tokens.length; i += 1) {
- const nToken: number = +tokens[i];
- embedArray.push(nToken);
- }
-
- embeddings.push(embedArray);
- }
-
- return embeddings;
- }
-
- /**
- * Generates an embedding for a single text.
- * @param text - A string to generate an embedding for.
- * @returns A Promise that resolves to an array of numbers representing the embedding.
- */
- async embedQuery(text: string): Promise {
- const tokens: number[] = [];
-
- const encodings = await this.caller.call(
- () =>
- new Promise((resolve) => {
- resolve(this._context.encode(text));
- })
- );
-
- for (let i = 0; i < encodings.length; i += 1) {
- const token: number = +encodings[i];
- tokens.push(token);
- }
-
- return tokens;
- }
-}
+export * from "@langchain/community/embeddings/llama_cpp";
diff --git a/langchain/src/embeddings/minimax.ts b/langchain/src/embeddings/minimax.ts
index 80697e30f60a..8568bf09207e 100644
--- a/langchain/src/embeddings/minimax.ts
+++ b/langchain/src/embeddings/minimax.ts
@@ -1,222 +1 @@
-import { getEnvironmentVariable } from "../util/env.js";
-import { chunkArray } from "../util/chunk.js";
-import { Embeddings, EmbeddingsParams } from "./base.js";
-import { ConfigurationParameters } from "../chat_models/minimax.js";
-
-/**
- * Interface for MinimaxEmbeddings parameters. Extends EmbeddingsParams and
- * defines additional parameters specific to the MinimaxEmbeddings class.
- */
-export interface MinimaxEmbeddingsParams extends EmbeddingsParams {
- /** Model name to use */
- modelName: string;
-
- /**
- * API key to use when making requests. Defaults to the value of
- * `MINIMAX_GROUP_ID` environment variable.
- */
- minimaxGroupId?: string;
-
- /**
- * Secret key to use when making requests. Defaults to the value of
- * `MINIMAX_API_KEY` environment variable.
- */
- minimaxApiKey?: string;
-
- /**
- * The maximum number of documents to embed in a single request. This is
- * limited by the Minimax API to a maximum of 4096.
- */
- batchSize?: number;
-
- /**
- * Whether to strip new lines from the input text. This is recommended by
- * Minimax, but may not be suitable for all use cases.
- */
- stripNewLines?: boolean;
-
- /**
- * The target use-case after generating the vector.
- * When using embeddings, the vector of the target content is first generated through the db and stored in the vector database,
- * and then the vector of the retrieval text is generated through the query.
- * Note: For the parameters of the partial algorithm, we adopted a separate algorithm plan for query and db.
- * Therefore, for a paragraph of text, if it is to be used as a retrieval text, it should use the db,
- * and if it is used as a retrieval text, it should use the query.
- */
- type?: "db" | "query";
-}
-
-export interface CreateMinimaxEmbeddingRequest {
- /**
- * @type {string}
- * @memberof CreateMinimaxEmbeddingRequest
- */
- model: string;
-
- /**
- * Text to generate vector expectation
- * @type {CreateEmbeddingRequestInput}
- * @memberof CreateMinimaxEmbeddingRequest
- */
- texts: string[];
-
- /**
- * The target use-case after generating the vector. When using embeddings,
- * first generate the vector of the target content through the db and store it in the vector database,
- * and then generate the vector of the retrieval text through the query.
- * Note: For the parameter of the algorithm, we use the algorithm scheme of query and db separation,
- * so a text, if it is to be retrieved as a text, should use the db,
- * if it is used as a retrieval text, should use the query.
- * @type {string}
- * @memberof CreateMinimaxEmbeddingRequest
- */
- type: "db" | "query";
-}
-
-/**
- * Class for generating embeddings using the Minimax API. Extends the
- * Embeddings class and implements MinimaxEmbeddingsParams
- * @example
- * ```typescript
- * const embeddings = new MinimaxEmbeddings();
- *
- * // Embed a single query
- * const queryEmbedding = await embeddings.embedQuery("Hello world");
- * console.log(queryEmbedding);
- *
- * // Embed multiple documents
- * const documentsEmbedding = await embeddings.embedDocuments([
- * "Hello world",
- * "Bye bye",
- * ]);
- * console.log(documentsEmbedding);
- * ```
- */
-export class MinimaxEmbeddings
- extends Embeddings
- implements MinimaxEmbeddingsParams
-{
- modelName = "embo-01";
-
- batchSize = 512;
-
- stripNewLines = true;
-
- minimaxGroupId?: string;
-
- minimaxApiKey?: string;
-
- type: "db" | "query" = "db";
-
- apiUrl: string;
-
- basePath?: string = "https://api.minimax.chat/v1";
-
- headers?: Record;
-
- constructor(
- fields?: Partial & {
- configuration?: ConfigurationParameters;
- }
- ) {
- const fieldsWithDefaults = { maxConcurrency: 2, ...fields };
- super(fieldsWithDefaults);
-
- this.minimaxGroupId =
- fields?.minimaxGroupId ?? getEnvironmentVariable("MINIMAX_GROUP_ID");
- if (!this.minimaxGroupId) {
- throw new Error("Minimax GroupID not found");
- }
-
- this.minimaxApiKey =
- fields?.minimaxApiKey ?? getEnvironmentVariable("MINIMAX_API_KEY");
-
- if (!this.minimaxApiKey) {
- throw new Error("Minimax ApiKey not found");
- }
-
- this.modelName = fieldsWithDefaults?.modelName ?? this.modelName;
- this.batchSize = fieldsWithDefaults?.batchSize ?? this.batchSize;
- this.type = fieldsWithDefaults?.type ?? this.type;
- this.stripNewLines =
- fieldsWithDefaults?.stripNewLines ?? this.stripNewLines;
- this.basePath = fields?.configuration?.basePath ?? this.basePath;
- this.apiUrl = `${this.basePath}/embeddings`;
- this.headers = fields?.configuration?.headers ?? this.headers;
- }
-
- /**
- * Method to generate embeddings for an array of documents. Splits the
- * documents into batches and makes requests to the Minimax 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) =>
- this.embeddingWithRetry({
- model: this.modelName,
- texts: batch,
- type: this.type,
- })
- );
- const batchResponses = await Promise.all(batchRequests);
-
- const embeddings: number[][] = [];
- for (let i = 0; i < batchResponses.length; i += 1) {
- const batch = batches[i];
- const { vectors: 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 { vectors } = await this.embeddingWithRetry({
- model: this.modelName,
- texts: [this.stripNewLines ? text.replace(/\n/g, " ") : text],
- type: this.type,
- });
- return vectors[0];
- }
-
- /**
- * Private method to make a request to the Minimax API to generate
- * embeddings. Handles the retry logic and returns the response from the
- * API.
- * @param request Request to send to the Minimax API.
- * @returns Promise that resolves to the response from the API.
- */
- private async embeddingWithRetry(request: CreateMinimaxEmbeddingRequest) {
- const makeCompletionRequest = async () => {
- const url = `${this.apiUrl}?GroupId=${this.minimaxGroupId}`;
- const response = await fetch(url, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- Authorization: `Bearer ${this.minimaxApiKey}`,
- ...this.headers,
- },
- body: JSON.stringify(request),
- });
-
- const json = await response.json();
- return json;
- };
-
- return this.caller.call(makeCompletionRequest);
- }
-}
+export * from "@langchain/community/embeddings/minimax";
diff --git a/langchain/src/embeddings/ollama.ts b/langchain/src/embeddings/ollama.ts
index de9c77797dfe..9bd994c08dd9 100644
--- a/langchain/src/embeddings/ollama.ts
+++ b/langchain/src/embeddings/ollama.ts
@@ -1,148 +1 @@
-import { OllamaInput, OllamaRequestParams } from "../util/ollama.js";
-import { Embeddings, EmbeddingsParams } from "./base.js";
-
-type CamelCasedRequestOptions = Omit<
- OllamaInput,
- "baseUrl" | "model" | "format"
->;
-
-/**
- * Interface for OllamaEmbeddings parameters. Extends EmbeddingsParams and
- * defines additional parameters specific to the OllamaEmbeddings class.
- */
-interface OllamaEmbeddingsParams extends EmbeddingsParams {
- /** The Ollama model to use, e.g: "llama2:13b" */
- model?: string;
-
- /** Base URL of the Ollama server, defaults to "http://localhost:11434" */
- baseUrl?: string;
-
- /** Advanced Ollama API request parameters in camelCase, see
- * https://github.com/jmorganca/ollama/blob/main/docs/modelfile.md#valid-parameters-and-values
- * for details of the available parameters.
- */
- requestOptions?: CamelCasedRequestOptions;
-}
-
-export class OllamaEmbeddings extends Embeddings {
- model = "llama2";
-
- baseUrl = "http://localhost:11434";
-
- requestOptions?: OllamaRequestParams["options"];
-
- constructor(params?: OllamaEmbeddingsParams) {
- super(params || {});
-
- if (params?.model) {
- this.model = params.model;
- }
-
- if (params?.baseUrl) {
- this.baseUrl = params.baseUrl;
- }
-
- if (params?.requestOptions) {
- this.requestOptions = this._convertOptions(params.requestOptions);
- }
- }
-
- /** convert camelCased Ollama request options like "useMMap" to
- * the snake_cased equivalent which the ollama API actually uses.
- * Used only for consistency with the llms/Ollama and chatModels/Ollama classes
- */
- _convertOptions(requestOptions: CamelCasedRequestOptions) {
- const snakeCasedOptions: Record = {};
- const mapping: Record = {
- embeddingOnly: "embedding_only",
- f16KV: "f16_kv",
- frequencyPenalty: "frequency_penalty",
- logitsAll: "logits_all",
- lowVram: "low_vram",
- mainGpu: "main_gpu",
- mirostat: "mirostat",
- mirostatEta: "mirostat_eta",
- mirostatTau: "mirostat_tau",
- numBatch: "num_batch",
- numCtx: "num_ctx",
- numGpu: "num_gpu",
- numGqa: "num_gqa",
- numKeep: "num_keep",
- numThread: "num_thread",
- penalizeNewline: "penalize_newline",
- presencePenalty: "presence_penalty",
- repeatLastN: "repeat_last_n",
- repeatPenalty: "repeat_penalty",
- ropeFrequencyBase: "rope_frequency_base",
- ropeFrequencyScale: "rope_frequency_scale",
- temperature: "temperature",
- stop: "stop",
- tfsZ: "tfs_z",
- topK: "top_k",
- topP: "top_p",
- typicalP: "typical_p",
- useMLock: "use_mlock",
- useMMap: "use_mmap",
- vocabOnly: "vocab_only",
- };
-
- for (const [key, value] of Object.entries(requestOptions)) {
- const snakeCasedOption = mapping[key as keyof CamelCasedRequestOptions];
- if (snakeCasedOption) {
- snakeCasedOptions[snakeCasedOption] = value;
- }
- }
- return snakeCasedOptions;
- }
-
- async _request(prompt: string): Promise {
- const { model, baseUrl, requestOptions } = this;
-
- let formattedBaseUrl = baseUrl;
- if (formattedBaseUrl.startsWith("http://localhost:")) {
- // Node 18 has issues with resolving "localhost"
- // See https://github.com/node-fetch/node-fetch/issues/1624
- formattedBaseUrl = formattedBaseUrl.replace(
- "http://localhost:",
- "http://127.0.0.1:"
- );
- }
-
- const response = await fetch(`${formattedBaseUrl}/api/embeddings`, {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify({
- prompt,
- model,
- options: requestOptions,
- }),
- });
- if (!response.ok) {
- throw new Error(
- `Request to Ollama server failed: ${response.status} ${response.statusText}`
- );
- }
-
- const json = await response.json();
- return json.embedding;
- }
-
- async _embed(strings: string[]): Promise {
- const embeddings: number[][] = [];
-
- for await (const prompt of strings) {
- const embedding = await this.caller.call(() => this._request(prompt));
- embeddings.push(embedding);
- }
-
- return embeddings;
- }
-
- async embedDocuments(documents: string[]) {
- return this._embed(documents);
- }
-
- async embedQuery(document: string) {
- return (await this.embedDocuments([document]))[0];
- }
-}
+export * from "@langchain/community/embeddings/ollama";
diff --git a/langchain/src/embeddings/openai.ts b/langchain/src/embeddings/openai.ts
index 0cc726d03ca3..9c5af9d81995 100644
--- a/langchain/src/embeddings/openai.ts
+++ b/langchain/src/embeddings/openai.ts
@@ -1,269 +1,4 @@
-import { type ClientOptions, OpenAI as OpenAIClient } from "openai";
-import { getEnvironmentVariable } from "../util/env.js";
-import {
- AzureOpenAIInput,
- OpenAICoreRequestOptions,
- LegacyOpenAIInput,
-} from "../types/openai-types.js";
-import { chunkArray } from "../util/chunk.js";
-import { Embeddings, EmbeddingsParams } from "./base.js";
-import { getEndpoint, OpenAIEndpointConfig } from "../util/azure.js";
-import { wrapOpenAIClientError } from "../util/openai.js";
-
-/**
- * Interface for OpenAIEmbeddings parameters. Extends EmbeddingsParams and
- * defines additional parameters specific to the OpenAIEmbeddings class.
- */
-export interface OpenAIEmbeddingsParams extends EmbeddingsParams {
- /** Model name to use */
- modelName: string;
-
- /**
- * Timeout to use when making requests to OpenAI.
- */
- timeout?: number;
-
- /**
- * The maximum number of documents to embed in a single request. This is
- * limited by the OpenAI API to a maximum of 2048.
- */
- batchSize?: number;
-
- /**
- * Whether to strip new lines from the input text. This is recommended by
- * OpenAI, but may not be suitable for all use cases.
- */
- stripNewLines?: boolean;
-}
-
-/**
- * Class for generating embeddings using the OpenAI API. Extends the
- * Embeddings class and implements OpenAIEmbeddingsParams and
- * AzureOpenAIInput.
- * @example
- * ```typescript
- * // Embed a query using OpenAIEmbeddings to generate embeddings for a given text
- * const model = new OpenAIEmbeddings();
- * const res = await model.embedQuery(
- * "What would be a good company name for a company that makes colorful socks?",
- * );
- * console.log({ res });
- *
- * ```
- */
-export class OpenAIEmbeddings
- extends Embeddings
- implements OpenAIEmbeddingsParams, AzureOpenAIInput
-{
- modelName = "text-embedding-ada-002";
-
- batchSize = 512;
-
- stripNewLines = true;
-
- timeout?: number;
-
- azureOpenAIApiVersion?: string;
-
- azureOpenAIApiKey?: string;
-
- azureOpenAIApiInstanceName?: string;
-
- azureOpenAIApiDeploymentName?: string;
-
- azureOpenAIBasePath?: string;
-
- organization?: string;
-
- private client: OpenAIClient;
-
- private clientConfig: ClientOptions;
-
- constructor(
- fields?: Partial &
- Partial & {
- verbose?: boolean;
- openAIApiKey?: string;
- configuration?: ClientOptions;
- },
- configuration?: ClientOptions & LegacyOpenAIInput
- ) {
- const fieldsWithDefaults = { maxConcurrency: 2, ...fields };
-
- super(fieldsWithDefaults);
-
- let apiKey =
- fieldsWithDefaults?.openAIApiKey ??
- getEnvironmentVariable("OPENAI_API_KEY");
-
- const azureApiKey =
- fieldsWithDefaults?.azureOpenAIApiKey ??
- getEnvironmentVariable("AZURE_OPENAI_API_KEY");
- if (!azureApiKey && !apiKey) {
- throw new Error("OpenAI or Azure OpenAI API key not found");
- }
-
- const azureApiInstanceName =
- fieldsWithDefaults?.azureOpenAIApiInstanceName ??
- getEnvironmentVariable("AZURE_OPENAI_API_INSTANCE_NAME");
-
- const azureApiDeploymentName =
- (fieldsWithDefaults?.azureOpenAIApiEmbeddingsDeploymentName ||
- fieldsWithDefaults?.azureOpenAIApiDeploymentName) ??
- (getEnvironmentVariable("AZURE_OPENAI_API_EMBEDDINGS_DEPLOYMENT_NAME") ||
- getEnvironmentVariable("AZURE_OPENAI_API_DEPLOYMENT_NAME"));
-
- const azureApiVersion =
- fieldsWithDefaults?.azureOpenAIApiVersion ??
- getEnvironmentVariable("AZURE_OPENAI_API_VERSION");
-
- this.azureOpenAIBasePath =
- fieldsWithDefaults?.azureOpenAIBasePath ??
- getEnvironmentVariable("AZURE_OPENAI_BASE_PATH");
-
- this.organization =
- fieldsWithDefaults?.configuration?.organization ??
- getEnvironmentVariable("OPENAI_ORGANIZATION");
-
- this.modelName = fieldsWithDefaults?.modelName ?? this.modelName;
- this.batchSize =
- fieldsWithDefaults?.batchSize ?? (azureApiKey ? 1 : this.batchSize);
- this.stripNewLines =
- fieldsWithDefaults?.stripNewLines ?? this.stripNewLines;
- this.timeout = fieldsWithDefaults?.timeout;
-
- this.azureOpenAIApiVersion = azureApiVersion;
- this.azureOpenAIApiKey = azureApiKey;
- this.azureOpenAIApiInstanceName = azureApiInstanceName;
- this.azureOpenAIApiDeploymentName = azureApiDeploymentName;
-
- if (this.azureOpenAIApiKey) {
- if (!this.azureOpenAIApiInstanceName && !this.azureOpenAIBasePath) {
- throw new Error("Azure OpenAI API instance name not found");
- }
- if (!this.azureOpenAIApiDeploymentName) {
- throw new Error("Azure OpenAI API deployment name not found");
- }
- if (!this.azureOpenAIApiVersion) {
- throw new Error("Azure OpenAI API version not found");
- }
- apiKey = apiKey ?? "";
- }
-
- this.clientConfig = {
- apiKey,
- organization: this.organization,
- baseURL: configuration?.basePath,
- dangerouslyAllowBrowser: true,
- defaultHeaders: configuration?.baseOptions?.headers,
- defaultQuery: configuration?.baseOptions?.params,
- ...configuration,
- ...fields?.configuration,
- };
- }
-
- /**
- * Method to generate embeddings for an array of documents. Splits the
- * documents into batches and makes requests to the OpenAI 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) =>
- this.embeddingWithRetry({
- model: this.modelName,
- input: batch,
- })
- );
- const batchResponses = await Promise.all(batchRequests);
-
- const embeddings: number[][] = [];
- for (let i = 0; i < batchResponses.length; i += 1) {
- const batch = batches[i];
- const { data: batchResponse } = batchResponses[i];
- for (let j = 0; j < batch.length; j += 1) {
- embeddings.push(batchResponse[j].embedding);
- }
- }
- 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 { data } = await this.embeddingWithRetry({
- model: this.modelName,
- input: this.stripNewLines ? text.replace(/\n/g, " ") : text,
- });
- return data[0].embedding;
- }
-
- /**
- * Private method to make a request to the OpenAI API to generate
- * embeddings. Handles the retry logic and returns the response from the
- * API.
- * @param request Request to send to the OpenAI API.
- * @returns Promise that resolves to the response from the API.
- */
- private async embeddingWithRetry(
- request: OpenAIClient.EmbeddingCreateParams
- ) {
- if (!this.client) {
- const openAIEndpointConfig: OpenAIEndpointConfig = {
- azureOpenAIApiDeploymentName: this.azureOpenAIApiDeploymentName,
- azureOpenAIApiInstanceName: this.azureOpenAIApiInstanceName,
- azureOpenAIApiKey: this.azureOpenAIApiKey,
- azureOpenAIBasePath: this.azureOpenAIBasePath,
- baseURL: this.clientConfig.baseURL,
- };
-
- const endpoint = getEndpoint(openAIEndpointConfig);
-
- const params = {
- ...this.clientConfig,
- baseURL: endpoint,
- timeout: this.timeout,
- maxRetries: 0,
- };
-
- if (!params.baseURL) {
- delete params.baseURL;
- }
-
- this.client = new OpenAIClient(params);
- }
- const requestOptions: OpenAICoreRequestOptions = {};
- if (this.azureOpenAIApiKey) {
- requestOptions.headers = {
- "api-key": this.azureOpenAIApiKey,
- ...requestOptions.headers,
- };
- requestOptions.query = {
- "api-version": this.azureOpenAIApiVersion,
- ...requestOptions.query,
- };
- }
- return this.caller.call(async () => {
- try {
- const res = await this.client.embeddings.create(
- request,
- requestOptions
- );
- return res;
- } catch (e) {
- const error = wrapOpenAIClientError(e);
- throw error;
- }
- });
- }
-}
+export {
+ type OpenAIEmbeddingsParams,
+ OpenAIEmbeddings,
+} from "@langchain/openai";
diff --git a/langchain/src/embeddings/tensorflow.ts b/langchain/src/embeddings/tensorflow.ts
index 1fc198ccdb8f..cd09a7c82cf5 100644
--- a/langchain/src/embeddings/tensorflow.ts
+++ b/langchain/src/embeddings/tensorflow.ts
@@ -1,91 +1 @@
-import { load } from "@tensorflow-models/universal-sentence-encoder";
-import * as tf from "@tensorflow/tfjs-core";
-
-import { Embeddings, EmbeddingsParams } from "./base.js";
-
-/**
- * Interface that extends EmbeddingsParams and defines additional
- * parameters specific to the TensorFlowEmbeddings class.
- */
-export interface TensorFlowEmbeddingsParams extends EmbeddingsParams {}
-
-/**
- * Class that extends the Embeddings class and provides methods for
- * generating embeddings using the Universal Sentence Encoder model from
- * TensorFlow.js.
- * @example
- * ```typescript
- * const embeddings = new TensorFlowEmbeddings();
- * const store = new MemoryVectorStore(embeddings);
- *
- * const documents = [
- * "A document",
- * "Some other piece of text",
- * "One more",
- * "And another",
- * ];
- *
- * await store.addDocuments(
- * documents.map((pageContent) => new Document({ pageContent }))
- * );
- * ```
- */
-export class TensorFlowEmbeddings extends Embeddings {
- constructor(fields?: TensorFlowEmbeddingsParams) {
- super(fields ?? {});
-
- try {
- tf.backend();
- } catch (e) {
- throw new Error("No TensorFlow backend found, see instructions at ...");
- }
- }
-
- _cached: ReturnType;
-
- /**
- * Private method that loads the Universal Sentence Encoder model if it
- * hasn't been loaded already. It returns a promise that resolves to the
- * loaded model.
- * @returns Promise that resolves to the loaded Universal Sentence Encoder model.
- */
- private async load() {
- if (this._cached === undefined) {
- this._cached = load();
- }
- return this._cached;
- }
-
- private _embed(texts: string[]) {
- return this.caller.call(async () => {
- const model = await this.load();
- return model.embed(texts);
- });
- }
-
- /**
- * Method that takes a document as input and returns a promise that
- * resolves to an embedding for the document. It calls the _embed method
- * with the document as the input and processes the result to return a
- * single embedding.
- * @param document Document to generate an embedding for.
- * @returns Promise that resolves to an embedding for the input document.
- */
- embedQuery(document: string): Promise {
- return this._embed([document])
- .then((embeddings) => embeddings.array())
- .then((embeddings) => embeddings[0]);
- }
-
- /**
- * Method that takes an array of documents as input and returns a promise
- * that resolves to a 2D array of embeddings for each document. It calls
- * the _embed method with the documents as the input and processes the
- * result to return the embeddings.
- * @param documents Array of documents to generate embeddings for.
- * @returns Promise that resolves to a 2D array of embeddings for each input document.
- */
- embedDocuments(documents: string[]): Promise {
- return this._embed(documents).then((embeddings) => embeddings.array());
- }
-}
+export * from "@langchain/community/embeddings/tensorflow";
diff --git a/langchain/src/embeddings/voyage.ts b/langchain/src/embeddings/voyage.ts
index 6b4d03c7e210..ea725613d118 100644
--- a/langchain/src/embeddings/voyage.ts
+++ b/langchain/src/embeddings/voyage.ts
@@ -1,152 +1 @@
-import { chunkArray } from "../util/chunk.js";
-import { getEnvironmentVariable } from "../util/env.js";
-import { Embeddings, EmbeddingsParams } from "./base.js";
-
-/**
- * Interface that extends EmbeddingsParams and defines additional
- * parameters specific to the VoyageEmbeddings class.
- */
-export interface VoyageEmbeddingsParams extends EmbeddingsParams {
- modelName: string;
-
- /**
- * The maximum number of documents to embed in a single request. This is
- * limited by the Voyage AI API to a maximum of 8.
- */
- batchSize?: number;
-}
-
-/**
- * Interface for the request body to generate embeddings.
- */
-export interface CreateVoyageEmbeddingRequest {
- /**
- * @type {string}
- * @memberof CreateVoyageEmbeddingRequest
- */
- model: string;
-
- /**
- * Text to generate vector expectation
- * @type {CreateEmbeddingRequestInput}
- * @memberof CreateVoyageEmbeddingRequest
- */
- input: string | string[];
-}
-
-/**
- * A class for generating embeddings using the Voyage AI API.
- */
-export class VoyageEmbeddings
- extends Embeddings
- implements VoyageEmbeddingsParams
-{
- modelName = "voyage-01";
-
- batchSize = 8;
-
- private apiKey: string;
-
- basePath?: string = "https://api.voyageai.com/v1";
-
- apiUrl: string;
-
- headers?: Record;
-
- /**
- * Constructor for the VoyageEmbeddings class.
- * @param fields - An optional object with properties to configure the instance.
- */
- constructor(
- fields?: Partial & {
- verbose?: boolean;
- apiKey?: string;
- }
- ) {
- const fieldsWithDefaults = { ...fields };
-
- super(fieldsWithDefaults);
-
- const apiKey =
- fieldsWithDefaults?.apiKey || getEnvironmentVariable("VOYAGEAI_API_KEY");
-
- if (!apiKey) {
- throw new Error("Voyage AI API key not found");
- }
-
- this.modelName = fieldsWithDefaults?.modelName ?? this.modelName;
- this.batchSize = fieldsWithDefaults?.batchSize ?? this.batchSize;
- this.apiKey = apiKey;
- this.apiUrl = `${this.basePath}/embeddings`;
- }
-
- /**
- * Generates embeddings for an array of texts.
- * @param texts - An array of strings to generate embeddings for.
- * @returns A Promise that resolves to an array of embeddings.
- */
- async embedDocuments(texts: string[]): Promise {
- const batches = chunkArray(texts, this.batchSize);
-
- const batchRequests = batches.map((batch) =>
- this.embeddingWithRetry({
- model: this.modelName,
- input: batch,
- })
- );
-
- const batchResponses = await Promise.all(batchRequests);
-
- const embeddings: number[][] = [];
-
- for (let i = 0; i < batchResponses.length; i += 1) {
- const batch = batches[i];
- const { data: batchResponse } = batchResponses[i];
- for (let j = 0; j < batch.length; j += 1) {
- embeddings.push(batchResponse[j].embedding);
- }
- }
-
- return embeddings;
- }
-
- /**
- * Generates an embedding for a single text.
- * @param text - A string to generate an embedding for.
- * @returns A Promise that resolves to an array of numbers representing the embedding.
- */
- async embedQuery(text: string): Promise {
- const { data } = await this.embeddingWithRetry({
- model: this.modelName,
- input: text,
- });
-
- return data[0].embedding;
- }
-
- /**
- * Makes a request to the Voyage AI API to generate embeddings for an array of texts.
- * @param request - An object with properties to configure the request.
- * @returns A Promise that resolves to the response from the Voyage AI API.
- */
-
- private async embeddingWithRetry(request: CreateVoyageEmbeddingRequest) {
- const makeCompletionRequest = async () => {
- const url = `${this.apiUrl}`;
- const response = await fetch(url, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- Authorization: `Bearer ${this.apiKey}`,
- ...this.headers,
- },
- body: JSON.stringify(request),
- });
-
- const json = await response.json();
- return json;
- };
-
- return this.caller.call(makeCompletionRequest);
- }
-}
+export * from "@langchain/community/embeddings/voyage";
diff --git a/langchain/src/experimental/openai_assistant/index.ts b/langchain/src/experimental/openai_assistant/index.ts
index 2e39836f30f3..248ff9407977 100644
--- a/langchain/src/experimental/openai_assistant/index.ts
+++ b/langchain/src/experimental/openai_assistant/index.ts
@@ -1,4 +1,4 @@
-import { type ClientOptions, OpenAI as OpenAIClient } from "openai";
+import { type ClientOptions, OpenAIClient } from "@langchain/openai";
import { Runnable } from "../../schema/runnable/base.js";
import { sleep } from "../../util/time.js";
import type { RunnableConfig } from "../../schema/runnable/config.js";
diff --git a/langchain/src/experimental/openai_assistant/schema.ts b/langchain/src/experimental/openai_assistant/schema.ts
index 10d4ce2658f4..a74ca1fce69f 100644
--- a/langchain/src/experimental/openai_assistant/schema.ts
+++ b/langchain/src/experimental/openai_assistant/schema.ts
@@ -1,4 +1,4 @@
-import type { OpenAI as OpenAIClient } from "openai";
+import type { OpenAIClient } from "@langchain/openai";
import type { AgentFinish, AgentAction } from "../../schema/index.js";
export type OpenAIAssistantFinish = AgentFinish & {
diff --git a/langchain/src/experimental/openai_assistant/tests/openai_assistant.int.test.ts b/langchain/src/experimental/openai_assistant/tests/openai_assistant.int.test.ts
index d1dac7daed6a..27d86403fc7e 100644
--- a/langchain/src/experimental/openai_assistant/tests/openai_assistant.int.test.ts
+++ b/langchain/src/experimental/openai_assistant/tests/openai_assistant.int.test.ts
@@ -2,7 +2,7 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import { z } from "zod";
-import { OpenAI as OpenAIClient } from "openai";
+import { OpenAIClient } from "@langchain/openai";
import { AgentExecutor } from "../../../agents/executor.js";
import { StructuredTool } from "../../../tools/base.js";
import { OpenAIAssistantRunnable } from "../index.js";
diff --git a/langchain/src/experimental/openai_files/index.ts b/langchain/src/experimental/openai_files/index.ts
index 6522e906fd29..62f35dadf438 100644
--- a/langchain/src/experimental/openai_files/index.ts
+++ b/langchain/src/experimental/openai_files/index.ts
@@ -1,4 +1,4 @@
-import { OpenAI as OpenAIClient, type ClientOptions } from "openai";
+import { OpenAIClient, type ClientOptions } from "@langchain/openai";
import { Serializable } from "../../load/serializable.js";
export type OpenAIFilesInput = {
diff --git a/langchain/src/graphs/neo4j_graph.ts b/langchain/src/graphs/neo4j_graph.ts
index c404e7e3b2ad..99cc0011f46a 100644
--- a/langchain/src/graphs/neo4j_graph.ts
+++ b/langchain/src/graphs/neo4j_graph.ts
@@ -1,286 +1 @@
-import neo4j, { Neo4jError } from "neo4j-driver";
-
-interface Neo4jGraphConfig {
- url: string;
- username: string;
- password: string;
- database?: string;
-}
-
-interface StructuredSchema {
- nodeProps: { [key: NodeType["labels"]]: NodeType["properties"] };
- relProps: { [key: RelType["type"]]: RelType["properties"] };
- relationships: PathType[];
-}
-
-type NodeType = {
- labels: string;
- properties: { property: string; type: string }[];
-};
-type RelType = {
- type: string;
- properties: { property: string; type: string }[];
-};
-type PathType = { start: string; type: string; end: string };
-
-/**
- * @security *Security note*: Make sure that the database connection uses credentials
- * that are narrowly-scoped to only include necessary permissions.
- * Failure to do so may result in data corruption or loss, since the calling
- * code may attempt commands that would result in deletion, mutation
- * of data if appropriately prompted or reading sensitive data if such
- * data is present in the database.
- * The best way to guard against such negative outcomes is to (as appropriate)
- * limit the permissions granted to the credentials used with this tool.
- * For example, creating read only users for the database is a good way to
- * ensure that the calling code cannot mutate or delete data.
- *
- * @link See https://js.langchain.com/docs/security for more information.
- */
-export class Neo4jGraph {
- private driver: neo4j.Driver;
-
- private database: string;
-
- private schema = "";
-
- private structuredSchema: StructuredSchema = {
- nodeProps: {},
- relProps: {},
- relationships: [],
- };
-
- constructor({
- url,
- username,
- password,
- database = "neo4j",
- }: Neo4jGraphConfig) {
- try {
- this.driver = neo4j.driver(url, neo4j.auth.basic(username, password));
- this.database = database;
- } catch (error) {
- throw new Error(
- "Could not create a Neo4j driver instance. Please check the connection details."
- );
- }
- }
-
- static async initialize(config: Neo4jGraphConfig): Promise {
- const graph = new Neo4jGraph(config);
-
- try {
- await graph.verifyConnectivity();
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- } catch (error: any) {
- console.log("Failed to verify connection.");
- }
-
- try {
- await graph.refreshSchema();
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- } catch (error: any) {
- const message = [
- "Could not use APOC procedures.",
- "Please ensure the APOC plugin is installed in Neo4j and that",
- "'apoc.meta.data()' is allowed in Neo4j configuration",
- ].join("\n");
-
- throw new Error(message);
- } finally {
- console.log("Schema refreshed successfully.");
- }
-
- return graph;
- }
-
- getSchema(): string {
- return this.schema;
- }
-
- getStructuredSchema() {
- return this.structuredSchema;
- }
-
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- async query(query: string, params: any = {}): Promise {
- try {
- const result = await this.driver.executeQuery(query, params, {
- database: this.database,
- });
- return toObjects(result.records);
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- } catch (error: any) {
- if (
- // eslint-disable-next-line
- error instanceof Neo4jError &&
- error.code === "Neo.ClientError.Procedure.ProcedureNotFound"
- ) {
- throw new Error("Procedure not found in Neo4j.");
- }
- }
- return undefined;
- }
-
- async verifyConnectivity() {
- await this.driver.verifyAuthentication();
- }
-
- async refreshSchema() {
- const nodePropertiesQuery = `
- CALL apoc.meta.data()
- YIELD label, other, elementType, type, property
- WHERE NOT type = "RELATIONSHIP" AND elementType = "node"
- WITH label AS nodeLabels, collect({property:property, type:type}) AS properties
- RETURN {labels: nodeLabels, properties: properties} AS output
- `;
-
- const relPropertiesQuery = `
- CALL apoc.meta.data()
- YIELD label, other, elementType, type, property
- WHERE NOT type = "RELATIONSHIP" AND elementType = "relationship"
- WITH label AS nodeLabels, collect({property:property, type:type}) AS properties
- RETURN {type: nodeLabels, properties: properties} AS output
- `;
-
- const relQuery = `
- CALL apoc.meta.data()
- YIELD label, other, elementType, type, property
- WHERE type = "RELATIONSHIP" AND elementType = "node"
- UNWIND other AS other_node
- RETURN {start: label, type: property, end: toString(other_node)} AS output
- `;
-
- // Assuming query method is defined and returns a Promise
- const nodeProperties: NodeType[] | undefined = (
- await this.query(nodePropertiesQuery)
- )?.map((el: { output: NodeType }) => el.output);
-
- const relationshipsProperties: RelType[] | undefined = (
- await this.query(relPropertiesQuery)
- )?.map((el: { output: RelType }) => el.output);
-
- const relationships: PathType[] | undefined = (
- await this.query(relQuery)
- )?.map((el: { output: PathType }) => el.output);
-
- // Structured schema similar to Python's dictionary comprehension
- this.structuredSchema = {
- nodeProps: Object.fromEntries(
- nodeProperties?.map((el) => [el.labels, el.properties]) || []
- ),
- relProps: Object.fromEntries(
- relationshipsProperties?.map((el) => [el.type, el.properties]) || []
- ),
- relationships: relationships || [],
- };
-
- // Format node properties
- const formattedNodeProps = nodeProperties?.map((el) => {
- const propsStr = el.properties
- .map((prop) => `${prop.property}: ${prop.type}`)
- .join(", ");
- return `${el.labels} {${propsStr}}`;
- });
-
- // Format relationship properties
- const formattedRelProps = relationshipsProperties?.map((el) => {
- const propsStr = el.properties
- .map((prop) => `${prop.property}: ${prop.type}`)
- .join(", ");
- return `${el.type} {${propsStr}}`;
- });
-
- // Format relationships
- const formattedRels = relationships?.map(
- (el) => `(:${el.start})-[:${el.type}]->(:${el.end})`
- );
-
- // Combine all formatted elements into a single string
- this.schema = [
- "Node properties are the following:",
- formattedNodeProps?.join(", "),
- "Relationship properties are the following:",
- formattedRelProps?.join(", "),
- "The relationships are the following:",
- formattedRels?.join(", "),
- ].join("\n");
- }
-
- async close() {
- await this.driver.close();
- }
-}
-
-function toObjects(records: neo4j.Record[]) {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- const recordValues: Record[] = records.map((record) => {
- const rObj = record.toObject();
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- const out: { [key: string]: any } = {};
- Object.keys(rObj).forEach((key) => {
- out[key] = itemIntToString(rObj[key]);
- });
- return out;
- });
- return recordValues;
-}
-
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
-function itemIntToString(item: any): any {
- if (neo4j.isInt(item)) return item.toString();
- if (Array.isArray(item)) return item.map((ii) => itemIntToString(ii));
- if (["number", "string", "boolean"].indexOf(typeof item) !== -1) return item;
- if (item === null) return item;
- if (typeof item === "object") return objIntToString(item);
-}
-
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
-function objIntToString(obj: any) {
- const entry = extractFromNeoObjects(obj);
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- let newObj: any = null;
- if (Array.isArray(entry)) {
- newObj = entry.map((item) => itemIntToString(item));
- } else if (entry !== null && typeof entry === "object") {
- newObj = {};
- Object.keys(entry).forEach((key) => {
- newObj[key] = itemIntToString(entry[key]);
- });
- }
- return newObj;
-}
-
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
-function extractFromNeoObjects(obj: any) {
- if (
- // eslint-disable-next-line
- obj instanceof (neo4j.types.Node as any) ||
- // eslint-disable-next-line
- obj instanceof (neo4j.types.Relationship as any)
- ) {
- return obj.properties;
- // eslint-disable-next-line
- } else if (obj instanceof (neo4j.types.Path as any)) {
- // eslint-disable-next-line
- return [].concat.apply([], extractPathForRows(obj));
- }
- return obj;
-}
-
-const extractPathForRows = (path: neo4j.Path) => {
- let { segments } = path;
- // Zero length path. No relationship, end === start
- if (!Array.isArray(path.segments) || path.segments.length < 1) {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- segments = [{ ...path, end: null } as any];
- }
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- return segments.map((segment: any) =>
- [
- objIntToString(segment.start),
- objIntToString(segment.relationship),
- objIntToString(segment.end),
- ].filter((part) => part !== null)
- );
-};
+export * from "@langchain/community/graphs/neo4j_graph";
diff --git a/langchain/src/llms/ai21.ts b/langchain/src/llms/ai21.ts
index 66d63b97abc3..d68f4b637a87 100644
--- a/langchain/src/llms/ai21.ts
+++ b/langchain/src/llms/ai21.ts
@@ -1,199 +1 @@
-import { LLM, BaseLLMParams } from "./base.js";
-import { getEnvironmentVariable } from "../util/env.js";
-
-/**
- * Type definition for AI21 penalty data.
- */
-export type AI21PenaltyData = {
- scale: number;
- applyToWhitespaces: boolean;
- applyToPunctuations: boolean;
- applyToNumbers: boolean;
- applyToStopwords: boolean;
- applyToEmojis: boolean;
-};
-
-/**
- * Interface for AI21 input parameters.
- */
-export interface AI21Input extends BaseLLMParams {
- ai21ApiKey?: string;
- model?: string;
- temperature?: number;
- minTokens?: number;
- maxTokens?: number;
- topP?: number;
- presencePenalty?: AI21PenaltyData;
- countPenalty?: AI21PenaltyData;
- frequencyPenalty?: AI21PenaltyData;
- numResults?: number;
- logitBias?: Record;
- stop?: string[];
- baseUrl?: string;
-}
-
-/**
- * Class representing the AI21 language model. It extends the LLM (Large
- * Language Model) class, providing a standard interface for interacting
- * with the AI21 language model.
- */
-export class AI21 extends LLM implements AI21Input {
- model = "j2-jumbo-instruct";
-
- temperature = 0.7;
-
- maxTokens = 1024;
-
- minTokens = 0;
-
- topP = 1;
-
- presencePenalty = AI21.getDefaultAI21PenaltyData();
-
- countPenalty = AI21.getDefaultAI21PenaltyData();
-
- frequencyPenalty = AI21.getDefaultAI21PenaltyData();
-
- numResults = 1;
-
- logitBias?: Record;
-
- ai21ApiKey?: string;
-
- stop?: string[];
-
- baseUrl?: string;
-
- constructor(fields?: AI21Input) {
- super(fields ?? {});
-
- this.model = fields?.model ?? this.model;
- this.temperature = fields?.temperature ?? this.temperature;
- this.maxTokens = fields?.maxTokens ?? this.maxTokens;
- this.minTokens = fields?.minTokens ?? this.minTokens;
- this.topP = fields?.topP ?? this.topP;
- this.presencePenalty = fields?.presencePenalty ?? this.presencePenalty;
- this.countPenalty = fields?.countPenalty ?? this.countPenalty;
- this.frequencyPenalty = fields?.frequencyPenalty ?? this.frequencyPenalty;
- this.numResults = fields?.numResults ?? this.numResults;
- this.logitBias = fields?.logitBias;
- this.ai21ApiKey =
- fields?.ai21ApiKey ?? getEnvironmentVariable("AI21_API_KEY");
- this.stop = fields?.stop;
- this.baseUrl = fields?.baseUrl;
- }
-
- /**
- * Method to validate the environment. It checks if the AI21 API key is
- * set. If not, it throws an error.
- */
- validateEnvironment() {
- if (!this.ai21ApiKey) {
- throw new Error(
- `No AI21 API key found. Please set it as "AI21_API_KEY" in your environment variables.`
- );
- }
- }
-
- /**
- * Static method to get the default penalty data for AI21.
- * @returns AI21PenaltyData
- */
- static getDefaultAI21PenaltyData(): AI21PenaltyData {
- return {
- scale: 0,
- applyToWhitespaces: true,
- applyToPunctuations: true,
- applyToNumbers: true,
- applyToStopwords: true,
- applyToEmojis: true,
- };
- }
-
- /** Get the type of LLM. */
- _llmType() {
- return "ai21";
- }
-
- /** Get the default parameters for calling AI21 API. */
- get defaultParams() {
- return {
- temperature: this.temperature,
- maxTokens: this.maxTokens,
- minTokens: this.minTokens,
- topP: this.topP,
- presencePenalty: this.presencePenalty,
- countPenalty: this.countPenalty,
- frequencyPenalty: this.frequencyPenalty,
- numResults: this.numResults,
- logitBias: this.logitBias,
- };
- }
-
- /** Get the identifying parameters for this LLM. */
- get identifyingParams() {
- return { ...this.defaultParams, model: this.model };
- }
-
- /** Call out to AI21's complete endpoint.
- Args:
- prompt: The prompt to pass into the model.
- stop: Optional list of stop words to use when generating.
-
- Returns:
- The string generated by the model.
-
- Example:
- let response = ai21._call("Tell me a joke.");
- */
- async _call(
- prompt: string,
- options: this["ParsedCallOptions"]
- ): Promise {
- let stop = options?.stop;
- this.validateEnvironment();
- if (this.stop && stop && this.stop.length > 0 && stop.length > 0) {
- throw new Error("`stop` found in both the input and default params.");
- }
- stop = this.stop ?? stop ?? [];
-
- const baseUrl =
- this.baseUrl ?? this.model === "j1-grande-instruct"
- ? "https://api.ai21.com/studio/v1/experimental"
- : "https://api.ai21.com/studio/v1";
-
- const url = `${baseUrl}/${this.model}/complete`;
- const headers = {
- Authorization: `Bearer ${this.ai21ApiKey}`,
- "Content-Type": "application/json",
- };
- const data = { prompt, stopSequences: stop, ...this.defaultParams };
- const responseData = await this.caller.callWithOptions({}, async () => {
- const response = await fetch(url, {
- method: "POST",
- headers,
- body: JSON.stringify(data),
- signal: options.signal,
- });
- if (!response.ok) {
- const error = new Error(
- `AI21 call failed with status code ${response.status}`
- );
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- (error as any).response = response;
- throw error;
- }
- return response.json();
- });
-
- if (
- !responseData.completions ||
- responseData.completions.length === 0 ||
- !responseData.completions[0].data
- ) {
- throw new Error("No completions found in response");
- }
-
- return responseData.completions[0].data.text ?? "";
- }
-}
+export * from "@langchain/community/llms/ai21";
diff --git a/langchain/src/llms/aleph_alpha.ts b/langchain/src/llms/aleph_alpha.ts
index 0e8968327073..1d0c12be8e26 100644
--- a/langchain/src/llms/aleph_alpha.ts
+++ b/langchain/src/llms/aleph_alpha.ts
@@ -1,298 +1 @@
-import { LLM, BaseLLMParams } from "./base.js";
-import { getEnvironmentVariable } from "../util/env.js";
-
-/**
- * Interface for the input parameters specific to the Aleph Alpha LLM.
- */
-export interface AlephAlphaInput extends BaseLLMParams {
- model: string;
- maximum_tokens: number;
- minimum_tokens?: number;
- echo?: boolean;
- temperature?: number;
- top_k?: number;
- top_p?: number;
- presence_penalty?: number;
- frequency_penalty?: number;
- sequence_penalty?: number;
- sequence_penalty_min_length?: number;
- repetition_penalties_include_prompt?: boolean;
- repetition_penalties_include_completion?: boolean;
- use_multiplicative_presence_penalty?: boolean;
- use_multiplicative_frequency_penalty?: boolean;
- use_multiplicative_sequence_penalty?: boolean;
- penalty_bias?: string;
- penalty_exceptions?: string[];
- penalty_exceptions_include_stop_sequences?: boolean;
- best_of?: number;
- n?: number;
- logit_bias?: object;
- log_probs?: number;
- tokens?: boolean;
- raw_completion: boolean;
- disable_optimizations?: boolean;
- completion_bias_inclusion?: string[];
- completion_bias_inclusion_first_token_only: boolean;
- completion_bias_exclusion?: string[];
- completion_bias_exclusion_first_token_only: boolean;
- contextual_control_threshold?: number;
- control_log_additive: boolean;
- stop?: string[];
- aleph_alpha_api_key?: string;
- base_url: string;
-}
-
-/**
- * Specific implementation of a Large Language Model (LLM) designed to
- * interact with the Aleph Alpha API. It extends the base LLM class and
- * includes a variety of parameters for customizing the behavior of the
- * Aleph Alpha model.
- */
-export class AlephAlpha extends LLM implements AlephAlphaInput {
- model = "luminous-base";
-
- maximum_tokens = 64;
-
- minimum_tokens = 0;
-
- echo: boolean;
-
- temperature = 0.0;
-
- top_k: number;
-
- top_p = 0.0;
-
- presence_penalty?: number;
-
- frequency_penalty?: number;
-
- sequence_penalty?: number;
-
- sequence_penalty_min_length?: number;
-
- repetition_penalties_include_prompt?: boolean;
-
- repetition_penalties_include_completion?: boolean;
-
- use_multiplicative_presence_penalty?: boolean;
-
- use_multiplicative_frequency_penalty?: boolean;
-
- use_multiplicative_sequence_penalty?: boolean;
-
- penalty_bias?: string;
-
- penalty_exceptions?: string[];
-
- penalty_exceptions_include_stop_sequences?: boolean;
-
- best_of?: number;
-
- n?: number;
-
- logit_bias?: object;
-
- log_probs?: number;
-
- tokens?: boolean;
-
- raw_completion: boolean;
-
- disable_optimizations?: boolean;
-
- completion_bias_inclusion?: string[];
-
- completion_bias_inclusion_first_token_only: boolean;
-
- completion_bias_exclusion?: string[];
-
- completion_bias_exclusion_first_token_only: boolean;
-
- contextual_control_threshold?: number;
-
- control_log_additive: boolean;
-
- aleph_alpha_api_key? = getEnvironmentVariable("ALEPH_ALPHA_API_KEY");
-
- stop?: string[];
-
- base_url = "https://api.aleph-alpha.com/complete";
-
- constructor(fields: Partial) {
- super(fields ?? {});
- this.model = fields?.model ?? this.model;
- this.temperature = fields?.temperature ?? this.temperature;
- this.maximum_tokens = fields?.maximum_tokens ?? this.maximum_tokens;
- this.minimum_tokens = fields?.minimum_tokens ?? this.minimum_tokens;
- this.top_k = fields?.top_k ?? this.top_k;
- this.top_p = fields?.top_p ?? this.top_p;
- this.presence_penalty = fields?.presence_penalty ?? this.presence_penalty;
- this.frequency_penalty =
- fields?.frequency_penalty ?? this.frequency_penalty;
- this.sequence_penalty = fields?.sequence_penalty ?? this.sequence_penalty;
- this.sequence_penalty_min_length =
- fields?.sequence_penalty_min_length ?? this.sequence_penalty_min_length;
- this.repetition_penalties_include_prompt =
- fields?.repetition_penalties_include_prompt ??
- this.repetition_penalties_include_prompt;
- this.repetition_penalties_include_completion =
- fields?.repetition_penalties_include_completion ??
- this.repetition_penalties_include_completion;
- this.use_multiplicative_presence_penalty =
- fields?.use_multiplicative_presence_penalty ??
- this.use_multiplicative_presence_penalty;
- this.use_multiplicative_frequency_penalty =
- fields?.use_multiplicative_frequency_penalty ??
- this.use_multiplicative_frequency_penalty;
- this.use_multiplicative_sequence_penalty =
- fields?.use_multiplicative_sequence_penalty ??
- this.use_multiplicative_sequence_penalty;
- this.penalty_bias = fields?.penalty_bias ?? this.penalty_bias;
- this.penalty_exceptions =
- fields?.penalty_exceptions ?? this.penalty_exceptions;
- this.penalty_exceptions_include_stop_sequences =
- fields?.penalty_exceptions_include_stop_sequences ??
- this.penalty_exceptions_include_stop_sequences;
- this.best_of = fields?.best_of ?? this.best_of;
- this.n = fields?.n ?? this.n;
- this.logit_bias = fields?.logit_bias ?? this.logit_bias;
- this.log_probs = fields?.log_probs ?? this.log_probs;
- this.tokens = fields?.tokens ?? this.tokens;
- this.raw_completion = fields?.raw_completion ?? this.raw_completion;
- this.disable_optimizations =
- fields?.disable_optimizations ?? this.disable_optimizations;
- this.completion_bias_inclusion =
- fields?.completion_bias_inclusion ?? this.completion_bias_inclusion;
- this.completion_bias_inclusion_first_token_only =
- fields?.completion_bias_inclusion_first_token_only ??
- this.completion_bias_inclusion_first_token_only;
- this.completion_bias_exclusion =
- fields?.completion_bias_exclusion ?? this.completion_bias_exclusion;
- this.completion_bias_exclusion_first_token_only =
- fields?.completion_bias_exclusion_first_token_only ??
- this.completion_bias_exclusion_first_token_only;
- this.contextual_control_threshold =
- fields?.contextual_control_threshold ?? this.contextual_control_threshold;
- this.control_log_additive =
- fields?.control_log_additive ?? this.control_log_additive;
- this.aleph_alpha_api_key =
- fields?.aleph_alpha_api_key ?? this.aleph_alpha_api_key;
- this.stop = fields?.stop ?? this.stop;
- }
-
- /**
- * Validates the environment by ensuring the necessary Aleph Alpha API key
- * is available. Throws an error if the API key is missing.
- */
- validateEnvironment() {
- if (!this.aleph_alpha_api_key) {
- throw new Error(
- "Aleph Alpha API Key is missing in environment variables."
- );
- }
- }
-
- /** Get the default parameters for calling Aleph Alpha API. */
- get defaultParams() {
- return {
- model: this.model,
- temperature: this.temperature,
- maximum_tokens: this.maximum_tokens,
- minimum_tokens: this.minimum_tokens,
- top_k: this.top_k,
- top_p: this.top_p,
- presence_penalty: this.presence_penalty,
- frequency_penalty: this.frequency_penalty,
- sequence_penalty: this.sequence_penalty,
- sequence_penalty_min_length: this.sequence_penalty_min_length,
- repetition_penalties_include_prompt:
- this.repetition_penalties_include_prompt,
- repetition_penalties_include_completion:
- this.repetition_penalties_include_completion,
- use_multiplicative_presence_penalty:
- this.use_multiplicative_presence_penalty,
- use_multiplicative_frequency_penalty:
- this.use_multiplicative_frequency_penalty,
- use_multiplicative_sequence_penalty:
- this.use_multiplicative_sequence_penalty,
- penalty_bias: this.penalty_bias,
- penalty_exceptions: this.penalty_exceptions,
- penalty_exceptions_include_stop_sequences:
- this.penalty_exceptions_include_stop_sequences,
- best_of: this.best_of,
- n: this.n,
- logit_bias: this.logit_bias,
- log_probs: this.log_probs,
- tokens: this.tokens,
- raw_completion: this.raw_completion,
- disable_optimizations: this.disable_optimizations,
- completion_bias_inclusion: this.completion_bias_inclusion,
- completion_bias_inclusion_first_token_only:
- this.completion_bias_inclusion_first_token_only,
- completion_bias_exclusion: this.completion_bias_exclusion,
- completion_bias_exclusion_first_token_only:
- this.completion_bias_exclusion_first_token_only,
- contextual_control_threshold: this.contextual_control_threshold,
- control_log_additive: this.control_log_additive,
- };
- }
-
- /** Get the identifying parameters for this LLM. */
- get identifyingParams() {
- return { ...this.defaultParams };
- }
-
- /** Get the type of LLM. */
- _llmType(): string {
- return "aleph_alpha";
- }
-
- async _call(
- prompt: string,
- options: this["ParsedCallOptions"]
- ): Promise {
- let stop = options?.stop;
- this.validateEnvironment();
- if (this.stop && stop && this.stop.length > 0 && stop.length > 0) {
- throw new Error("`stop` found in both the input and default params.");
- }
- stop = this.stop ?? stop ?? [];
- const headers = {
- Authorization: `Bearer ${this.aleph_alpha_api_key}`,
- "Content-Type": "application/json",
- Accept: "application/json",
- };
- const data = { prompt, stop_sequences: stop, ...this.defaultParams };
- const responseData = await this.caller.call(async () => {
- const response = await fetch(this.base_url, {
- method: "POST",
- headers,
- body: JSON.stringify(data),
- signal: options.signal,
- });
- if (!response.ok) {
- // consume the response body to release the connection
- // https://undici.nodejs.org/#/?id=garbage-collection
- const text = await response.text();
- const error = new Error(
- `Aleph Alpha call failed with status ${response.status} and body ${text}`
- );
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- (error as any).response = response;
- throw error;
- }
- return response.json();
- });
-
- if (
- !responseData.completions ||
- responseData.completions.length === 0 ||
- !responseData.completions[0].completion
- ) {
- throw new Error("No completions found in response");
- }
-
- return responseData.completions[0].completion ?? "";
- }
-}
+export * from "@langchain/community/llms/aleph_alpha";
diff --git a/langchain/src/llms/bedrock/web.ts b/langchain/src/llms/bedrock/web.ts
index f10660c9feab..3ed2ccdd2650 100644
--- a/langchain/src/llms/bedrock/web.ts
+++ b/langchain/src/llms/bedrock/web.ts
@@ -1,356 +1 @@
-import { SignatureV4 } from "@smithy/signature-v4";
-
-import { HttpRequest } from "@smithy/protocol-http";
-import { EventStreamCodec } from "@smithy/eventstream-codec";
-import { fromUtf8, toUtf8 } from "@smithy/util-utf8";
-import { Sha256 } from "@aws-crypto/sha256-js";
-
-import {
- BaseBedrockInput,
- BedrockLLMInputOutputAdapter,
- type CredentialType,
-} from "../../util/bedrock.js";
-import { getEnvironmentVariable } from "../../util/env.js";
-import { LLM, BaseLLMParams } from "../base.js";
-import { CallbackManagerForLLMRun } from "../../callbacks/manager.js";
-import { GenerationChunk } from "../../schema/index.js";
-import type { SerializedFields } from "../../load/map_keys.js";
-
-/**
- * A type of Large Language Model (LLM) that interacts with the Bedrock
- * service. It extends the base `LLM` class and implements the
- * `BaseBedrockInput` interface. The class is designed to authenticate and
- * interact with the Bedrock service, which is a part of Amazon Web
- * Services (AWS). It uses AWS credentials for authentication and can be
- * configured with various parameters such as the model to use, the AWS
- * region, and the maximum number of tokens to generate.
- */
-export class Bedrock extends LLM implements BaseBedrockInput {
- model = "amazon.titan-tg1-large";
-
- region: string;
-
- credentials: CredentialType;
-
- temperature?: number | undefined = undefined;
-
- maxTokens?: number | undefined = undefined;
-
- fetchFn: typeof fetch;
-
- endpointHost?: string;
-
- /** @deprecated */
- stopSequences?: string[];
-
- modelKwargs?: Record;
-
- codec: EventStreamCodec = new EventStreamCodec(toUtf8, fromUtf8);
-
- streaming = false;
-
- lc_serializable = true;
-
- get lc_aliases(): Record {
- return {
- model: "model_id",
- region: "region_name",
- };
- }
-
- get lc_secrets(): { [key: string]: string } | undefined {
- return {
- "credentials.accessKeyId": "BEDROCK_AWS_ACCESS_KEY_ID",
- "credentials.secretAccessKey": "BEDROCK_AWS_SECRET_ACCESS_KEY",
- };
- }
-
- get lc_attributes(): SerializedFields | undefined {
- return { region: this.region };
- }
-
- _llmType() {
- return "bedrock";
- }
-
- static lc_name() {
- return "Bedrock";
- }
-
- constructor(fields?: Partial & BaseLLMParams) {
- super(fields ?? {});
-
- this.model = fields?.model ?? this.model;
- const allowedModels = ["ai21", "anthropic", "amazon", "cohere", "meta"];
- if (!allowedModels.includes(this.model.split(".")[0])) {
- throw new Error(
- `Unknown model: '${this.model}', only these are supported: ${allowedModels}`
- );
- }
- const region =
- fields?.region ?? getEnvironmentVariable("AWS_DEFAULT_REGION");
- if (!region) {
- throw new Error(
- "Please set the AWS_DEFAULT_REGION environment variable or pass it to the constructor as the region field."
- );
- }
- this.region = region;
-
- const credentials = fields?.credentials;
- if (!credentials) {
- throw new Error(
- "Please set the AWS credentials in the 'credentials' field."
- );
- }
- this.credentials = credentials;
-
- this.temperature = fields?.temperature ?? this.temperature;
- this.maxTokens = fields?.maxTokens ?? this.maxTokens;
- this.fetchFn = fields?.fetchFn ?? fetch.bind(globalThis);
- this.endpointHost = fields?.endpointHost ?? fields?.endpointUrl;
- this.stopSequences = fields?.stopSequences;
- this.modelKwargs = fields?.modelKwargs;
- this.streaming = fields?.streaming ?? this.streaming;
- }
-
- /** Call out to Bedrock service model.
- Arguments:
- prompt: The prompt to pass into the model.
-
- Returns:
- The string generated by the model.
-
- Example:
- response = model.call("Tell me a joke.")
- */
- async _call(
- prompt: string,
- options: this["ParsedCallOptions"],
- runManager?: CallbackManagerForLLMRun
- ): Promise {
- const service = "bedrock-runtime";
- const endpointHost =
- this.endpointHost ?? `${service}.${this.region}.amazonaws.com`;
- const provider = this.model.split(".")[0];
- if (this.streaming) {
- const stream = this._streamResponseChunks(prompt, options, runManager);
- let finalResult: GenerationChunk | undefined;
- for await (const chunk of stream) {
- if (finalResult === undefined) {
- finalResult = chunk;
- } else {
- finalResult = finalResult.concat(chunk);
- }
- }
- return finalResult?.text ?? "";
- }
- const response = await this._signedFetch(prompt, options, {
- bedrockMethod: "invoke",
- endpointHost,
- provider,
- });
- const json = await response.json();
- if (!response.ok) {
- throw new Error(
- `Error ${response.status}: ${json.message ?? JSON.stringify(json)}`
- );
- }
- const text = BedrockLLMInputOutputAdapter.prepareOutput(provider, json);
- return text;
- }
-
- async _signedFetch(
- prompt: string,
- options: this["ParsedCallOptions"],
- fields: {
- bedrockMethod: "invoke" | "invoke-with-response-stream";
- endpointHost: string;
- provider: string;
- }
- ) {
- const { bedrockMethod, endpointHost, provider } = fields;
- const inputBody = BedrockLLMInputOutputAdapter.prepareInput(
- provider,
- prompt,
- this.maxTokens,
- this.temperature,
- options.stop ?? this.stopSequences,
- this.modelKwargs,
- fields.bedrockMethod
- );
-
- const url = new URL(
- `https://${endpointHost}/model/${this.model}/${bedrockMethod}`
- );
-
- const request = new HttpRequest({
- hostname: url.hostname,
- path: url.pathname,
- protocol: url.protocol,
- method: "POST", // method must be uppercase
- body: JSON.stringify(inputBody),
- query: Object.fromEntries(url.searchParams.entries()),
- headers: {
- // host is required by AWS Signature V4: https://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
- host: url.host,
- accept: "application/json",
- "content-type": "application/json",
- },
- });
-
- const signer = new SignatureV4({
- credentials: this.credentials,
- service: "bedrock",
- region: this.region,
- sha256: Sha256,
- });
-
- const signedRequest = await signer.sign(request);
-
- // Send request to AWS using the low-level fetch API
- const response = await this.caller.callWithOptions(
- { signal: options.signal },
- async () =>
- this.fetchFn(url, {
- headers: signedRequest.headers,
- body: signedRequest.body,
- method: signedRequest.method,
- })
- );
- return response;
- }
-
- invocationParams(options?: this["ParsedCallOptions"]) {
- return {
- model: this.model,
- region: this.region,
- temperature: this.temperature,
- maxTokens: this.maxTokens,
- stop: options?.stop ?? this.stopSequences,
- modelKwargs: this.modelKwargs,
- };
- }
-
- async *_streamResponseChunks(
- prompt: string,
- options: this["ParsedCallOptions"],
- runManager?: CallbackManagerForLLMRun
- ): AsyncGenerator {
- const provider = this.model.split(".")[0];
- const bedrockMethod =
- provider === "anthropic" || provider === "cohere" || provider === "meta"
- ? "invoke-with-response-stream"
- : "invoke";
-
- const service = "bedrock-runtime";
- const endpointHost =
- this.endpointHost ?? `${service}.${this.region}.amazonaws.com`;
-
- // Send request to AWS using the low-level fetch API
- const response = await this._signedFetch(prompt, options, {
- bedrockMethod,
- endpointHost,
- provider,
- });
-
- if (response.status < 200 || response.status >= 300) {
- throw Error(
- `Failed to access underlying url '${endpointHost}': got ${
- response.status
- } ${response.statusText}: ${await response.text()}`
- );
- }
-
- if (
- provider === "anthropic" ||
- provider === "cohere" ||
- provider === "meta"
- ) {
- const reader = response.body?.getReader();
- const decoder = new TextDecoder();
- for await (const chunk of this._readChunks(reader)) {
- const event = this.codec.decode(chunk);
- if (
- (event.headers[":event-type"] !== undefined &&
- event.headers[":event-type"].value !== "chunk") ||
- event.headers[":content-type"].value !== "application/json"
- ) {
- throw Error(`Failed to get event chunk: got ${chunk}`);
- }
- const body = JSON.parse(decoder.decode(event.body));
- if (body.message) {
- throw new Error(body.message);
- }
- if (body.bytes !== undefined) {
- const chunkResult = JSON.parse(
- decoder.decode(
- Uint8Array.from(atob(body.bytes), (m) => m.codePointAt(0) ?? 0)
- )
- );
- const text = BedrockLLMInputOutputAdapter.prepareOutput(
- provider,
- chunkResult
- );
- yield new GenerationChunk({
- text,
- generationInfo: {},
- });
- // eslint-disable-next-line no-void
- void runManager?.handleLLMNewToken(text);
- }
- }
- } else {
- const json = await response.json();
- const text = BedrockLLMInputOutputAdapter.prepareOutput(provider, json);
- yield new GenerationChunk({
- text,
- generationInfo: {},
- });
- // eslint-disable-next-line no-void
- void runManager?.handleLLMNewToken(text);
- }
- }
-
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- _readChunks(reader: any) {
- function _concatChunks(a: Uint8Array, b: Uint8Array) {
- const newBuffer = new Uint8Array(a.length + b.length);
- newBuffer.set(a);
- newBuffer.set(b, a.length);
- return newBuffer;
- }
-
- function getMessageLength(buffer: Uint8Array) {
- if (buffer.byteLength === 0) return 0;
- const view = new DataView(
- buffer.buffer,
- buffer.byteOffset,
- buffer.byteLength
- );
-
- return view.getUint32(0, false);
- }
-
- return {
- async *[Symbol.asyncIterator]() {
- let readResult = await reader.read();
-
- let buffer: Uint8Array = new Uint8Array(0);
- while (!readResult.done) {
- const chunk: Uint8Array = readResult.value;
-
- buffer = _concatChunks(buffer, chunk);
- let messageLength = getMessageLength(buffer);
-
- while (buffer.byteLength > 0 && buffer.byteLength >= messageLength) {
- yield buffer.slice(0, messageLength);
- buffer = buffer.slice(messageLength);
- messageLength = getMessageLength(buffer);
- }
-
- readResult = await reader.read();
- }
- },
- };
- }
-}
+export * from "@langchain/community/llms/bedrock/web";
diff --git a/langchain/src/llms/cloudflare_workersai.ts b/langchain/src/llms/cloudflare_workersai.ts
index 25c6b5a16276..2e5add32a465 100644
--- a/langchain/src/llms/cloudflare_workersai.ts
+++ b/langchain/src/llms/cloudflare_workersai.ts
@@ -1,189 +1 @@
-import { LLM, BaseLLMParams } from "./base.js";
-import { getEnvironmentVariable } from "../util/env.js";
-import { CallbackManagerForLLMRun } from "../callbacks/manager.js";
-import { GenerationChunk } from "../schema/index.js";
-import { convertEventStreamToIterableReadableDataStream } from "../util/event-source-parse.js";
-
-/**
- * Interface for CloudflareWorkersAI input parameters.
- */
-export interface CloudflareWorkersAIInput {
- cloudflareAccountId?: string;
- cloudflareApiToken?: string;
- model?: string;
- baseUrl?: string;
- streaming?: boolean;
-}
-
-/**
- * Class representing the CloudflareWorkersAI language model. It extends the LLM (Large
- * Language Model) class, providing a standard interface for interacting
- * with the CloudflareWorkersAI language model.
- */
-export class CloudflareWorkersAI
- extends LLM
- implements CloudflareWorkersAIInput
-{
- model = "@cf/meta/llama-2-7b-chat-int8";
-
- cloudflareAccountId?: string;
-
- cloudflareApiToken?: string;
-
- baseUrl: string;
-
- streaming = false;
-
- static lc_name() {
- return "CloudflareWorkersAI";
- }
-
- lc_serializable = true;
-
- constructor(fields?: CloudflareWorkersAIInput & BaseLLMParams) {
- super(fields ?? {});
-
- this.model = fields?.model ?? this.model;
- this.streaming = fields?.streaming ?? this.streaming;
- this.cloudflareAccountId =
- fields?.cloudflareAccountId ??
- getEnvironmentVariable("CLOUDFLARE_ACCOUNT_ID");
- this.cloudflareApiToken =
- fields?.cloudflareApiToken ??
- getEnvironmentVariable("CLOUDFLARE_API_TOKEN");
- this.baseUrl =
- fields?.baseUrl ??
- `https://api.cloudflare.com/client/v4/accounts/${this.cloudflareAccountId}/ai/run`;
- if (this.baseUrl.endsWith("/")) {
- this.baseUrl = this.baseUrl.slice(0, -1);
- }
- }
-
- /**
- * Method to validate the environment.
- */
- validateEnvironment() {
- if (this.baseUrl === undefined) {
- if (!this.cloudflareAccountId) {
- throw new Error(
- `No Cloudflare account ID found. Please provide it when instantiating the CloudflareWorkersAI class, or set it as "CLOUDFLARE_ACCOUNT_ID" in your environment variables.`
- );
- }
- if (!this.cloudflareApiToken) {
- throw new Error(
- `No Cloudflare API key found. Please provide it when instantiating the CloudflareWorkersAI class, or set it as "CLOUDFLARE_API_KEY" in your environment variables.`
- );
- }
- }
- }
-
- /** Get the identifying parameters for this LLM. */
- get identifyingParams() {
- return { model: this.model };
- }
-
- /**
- * Get the parameters used to invoke the model
- */
- invocationParams() {
- return {
- model: this.model,
- };
- }
-
- /** Get the type of LLM. */
- _llmType() {
- return "cloudflare";
- }
-
- async _request(
- prompt: string,
- options: this["ParsedCallOptions"],
- stream?: boolean
- ) {
- this.validateEnvironment();
-
- const url = `${this.baseUrl}/${this.model}`;
- const headers = {
- Authorization: `Bearer ${this.cloudflareApiToken}`,
- "Content-Type": "application/json",
- };
-
- const data = { prompt, stream };
- return this.caller.call(async () => {
- const response = await fetch(url, {
- method: "POST",
- headers,
- body: JSON.stringify(data),
- signal: options.signal,
- });
- if (!response.ok) {
- const error = new Error(
- `Cloudflare LLM call failed with status code ${response.status}`
- );
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- (error as any).response = response;
- throw error;
- }
- return response;
- });
- }
-
- async *_streamResponseChunks(
- prompt: string,
- options: this["ParsedCallOptions"],
- runManager?: CallbackManagerForLLMRun
- ): AsyncGenerator {
- const response = await this._request(prompt, options, true);
- if (!response.body) {
- throw new Error("Empty response from Cloudflare. Please try again.");
- }
- const stream = convertEventStreamToIterableReadableDataStream(
- response.body
- );
- for await (const chunk of stream) {
- if (chunk !== "[DONE]") {
- const parsedChunk = JSON.parse(chunk);
- const generationChunk = new GenerationChunk({
- text: parsedChunk.response,
- });
- yield generationChunk;
- // eslint-disable-next-line no-void
- void runManager?.handleLLMNewToken(generationChunk.text ?? "");
- }
- }
- }
-
- /** Call out to CloudflareWorkersAI's complete endpoint.
- Args:
- prompt: The prompt to pass into the model.
- Returns:
- The string generated by the model.
- Example:
- let response = CloudflareWorkersAI.call("Tell me a joke.");
- */
- async _call(
- prompt: string,
- options: this["ParsedCallOptions"],
- runManager?: CallbackManagerForLLMRun
- ): Promise {
- if (!this.streaming) {
- const response = await this._request(prompt, options);
-
- const responseData = await response.json();
-
- return responseData.result.response;
- } else {
- const stream = this._streamResponseChunks(prompt, options, runManager);
- let finalResult: GenerationChunk | undefined;
- for await (const chunk of stream) {
- if (finalResult === undefined) {
- finalResult = chunk;
- } else {
- finalResult = finalResult.concat(chunk);
- }
- }
- return finalResult?.text ?? "";
- }
- }
-}
+export * from "@langchain/community/llms/cloudflare_workersai";
diff --git a/langchain/src/llms/cohere.ts b/langchain/src/llms/cohere.ts
index 393876efb939..8b911819109e 100644
--- a/langchain/src/llms/cohere.ts
+++ b/langchain/src/llms/cohere.ts
@@ -1,129 +1 @@
-import { getEnvironmentVariable } from "../util/env.js";
-import { LLM, BaseLLMParams } from "./base.js";
-
-/**
- * Interface for the input parameters specific to the Cohere model.
- */
-export interface CohereInput extends BaseLLMParams {
- /** Sampling temperature to use */
- temperature?: number;
-
- /**
- * Maximum number of tokens to generate in the completion.
- */
- maxTokens?: number;
-
- /** Model to use */
- model?: string;
-
- apiKey?: string;
-}
-
-/**
- * Class representing a Cohere Large Language Model (LLM). It interacts
- * with the Cohere API to generate text completions.
- * @example
- * ```typescript
- * const model = new Cohere({
- * temperature: 0.7,
- * maxTokens: 20,
- * maxRetries: 5,
- * });
- *
- * const res = await model.call(
- * "Question: What would be a good company name for a company that makes colorful socks?\nAnswer:"
- * );
- * console.log({ res });
- * ```
- */
-export class Cohere extends LLM implements CohereInput {
- static lc_name() {
- return "Cohere";
- }
-
- get lc_secrets(): { [key: string]: string } | undefined {
- return {
- apiKey: "COHERE_API_KEY",
- };
- }
-
- get lc_aliases(): { [key: string]: string } | undefined {
- return {
- apiKey: "cohere_api_key",
- };
- }
-
- lc_serializable = true;
-
- temperature = 0;
-
- maxTokens = 250;
-
- model: string;
-
- apiKey: string;
-
- constructor(fields?: CohereInput) {
- super(fields ?? {});
-
- const apiKey = fields?.apiKey ?? getEnvironmentVariable("COHERE_API_KEY");
-
- if (!apiKey) {
- throw new Error(
- "Please set the COHERE_API_KEY environment variable or pass it to the constructor as the apiKey field."
- );
- }
-
- this.apiKey = apiKey;
- this.maxTokens = fields?.maxTokens ?? this.maxTokens;
- this.temperature = fields?.temperature ?? this.temperature;
- this.model = fields?.model ?? this.model;
- }
-
- _llmType() {
- return "cohere";
- }
-
- /** @ignore */
- async _call(
- prompt: string,
- options: this["ParsedCallOptions"]
- ): Promise {
- const { cohere } = await Cohere.imports();
-
- cohere.init(this.apiKey);
-
- // Hit the `generate` endpoint on the `large` model
- const generateResponse = await this.caller.callWithOptions(
- { signal: options.signal },
- cohere.generate.bind(cohere),
- {
- prompt,
- model: this.model,
- max_tokens: this.maxTokens,
- temperature: this.temperature,
- end_sequences: options.stop,
- }
- );
- try {
- return generateResponse.body.generations[0].text;
- } catch {
- console.log(generateResponse);
- throw new Error("Could not parse response.");
- }
- }
-
- /** @ignore */
- static async imports(): Promise<{
- cohere: typeof import("cohere-ai");
- }> {
- try {
- const { default: cohere } = await import("cohere-ai");
- return { cohere };
- } catch (e) {
- throw new Error(
- "Please install cohere-ai as a dependency with, e.g. `yarn add cohere-ai`"
- );
- }
- }
-}
+export * from "@langchain/community/llms/cohere";
diff --git a/langchain/src/llms/fireworks.ts b/langchain/src/llms/fireworks.ts
index 8dd5981aad69..c8ff87b2d830 100644
--- a/langchain/src/llms/fireworks.ts
+++ b/langchain/src/llms/fireworks.ts
@@ -1,140 +1 @@
-import type { OpenAI as OpenAIClient } from "openai";
-
-import type { BaseLLMParams } from "./base.js";
-import type { OpenAICallOptions, OpenAIInput } from "./openai.js";
-import type { OpenAICoreRequestOptions } from "../types/openai-types.js";
-import { getEnvironmentVariable } from "../util/env.js";
-import { OpenAI } from "./openai.js";
-
-type FireworksUnsupportedArgs =
- | "frequencyPenalty"
- | "presencePenalty"
- | "bestOf"
- | "logitBias";
-
-type FireworksUnsupportedCallOptions = "functions" | "function_call" | "tools";
-
-export type FireworksCallOptions = Partial<
- Omit
->;
-
-/**
- * Wrapper around Fireworks API for large language models
- *
- * 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.
- */
-export class Fireworks extends OpenAI {
- static lc_name() {
- return "Fireworks";
- }
-
- _llmType() {
- return "fireworks";
- }
-
- get lc_secrets(): { [key: string]: string } | undefined {
- return {
- fireworksApiKey: "FIREWORKS_API_KEY",
- };
- }
-
- lc_serializable = true;
-
- fireworksApiKey?: string;
-
- constructor(
- fields?: Partial<
- Omit
- > &
- BaseLLMParams & { fireworksApiKey?: string }
- ) {
- const fireworksApiKey =
- fields?.fireworksApiKey || getEnvironmentVariable("FIREWORKS_API_KEY");
-
- if (!fireworksApiKey) {
- throw new Error(
- `Fireworks API key not found. Please set the FIREWORKS_API_KEY environment variable or provide the key into "fireworksApiKey"`
- );
- }
-
- super({
- ...fields,
- openAIApiKey: fireworksApiKey,
- modelName: fields?.modelName || "accounts/fireworks/models/llama-v2-13b",
- configuration: {
- baseURL: "https://api.fireworks.ai/inference/v1",
- },
- });
-
- this.fireworksApiKey = fireworksApiKey;
- }
-
- toJSON() {
- const result = super.toJSON();
-
- if (
- "kwargs" in result &&
- typeof result.kwargs === "object" &&
- result.kwargs != null
- ) {
- delete result.kwargs.openai_api_key;
- delete result.kwargs.configuration;
- }
-
- return result;
- }
-
- async completionWithRetry(
- request: OpenAIClient.CompletionCreateParamsStreaming,
- options?: OpenAICoreRequestOptions
- ): Promise>;
-
- async completionWithRetry(
- request: OpenAIClient.CompletionCreateParamsNonStreaming,
- options?: OpenAICoreRequestOptions
- ): Promise;
-
- /**
- * Calls the Fireworks API with retry logic in case of failures.
- * @param request The request to send to the Fireworks API.
- * @param options Optional configuration for the API call.
- * @returns The response from the Fireworks API.
- */
- async completionWithRetry(
- request:
- | OpenAIClient.CompletionCreateParamsStreaming
- | OpenAIClient.CompletionCreateParamsNonStreaming,
- options?: OpenAICoreRequestOptions
- ): Promise<
- AsyncIterable | OpenAIClient.Completions.Completion
- > {
- // https://readme.fireworks.ai/docs/openai-compatibility#api-compatibility
- if (Array.isArray(request.prompt)) {
- if (request.prompt.length > 1) {
- throw new Error("Multiple prompts are not supported by Fireworks");
- }
-
- const prompt = request.prompt[0];
- if (typeof prompt !== "string") {
- throw new Error("Only string prompts are supported by Fireworks");
- }
-
- request.prompt = prompt;
- }
-
- delete request.frequency_penalty;
- delete request.presence_penalty;
- delete request.best_of;
- delete request.logit_bias;
-
- if (request.stream === true) {
- return super.completionWithRetry(request, options);
- }
-
- return super.completionWithRetry(request, options);
- }
-}
+export * from "@langchain/community/llms/fireworks";
diff --git a/langchain/src/llms/googlepalm.ts b/langchain/src/llms/googlepalm.ts
index 2bd8d8d2fc49..5e95faa32f13 100644
--- a/langchain/src/llms/googlepalm.ts
+++ b/langchain/src/llms/googlepalm.ts
@@ -1,203 +1 @@
-import { TextServiceClient, protos } from "@google-ai/generativelanguage";
-import { GoogleAuth } from "google-auth-library";
-import { BaseLLMParams, LLM } from "./base.js";
-import { getEnvironmentVariable } from "../util/env.js";
-
-/**
- * Input for Text generation for Google Palm
- */
-export interface GooglePaLMTextInput extends BaseLLMParams {
- /**
- * Model Name to use
- *
- * Note: The format must follow the pattern - `models/{model}`
- */
- modelName?: string;
-
- /**
- * Controls the randomness of the output.
- *
- * Values can range from [0.0,1.0], inclusive. A value closer to 1.0
- * will produce responses that are more varied and creative, while
- * a value closer to 0.0 will typically result in more straightforward
- * responses from the model.
- *
- * Note: The default value varies by model
- */
- temperature?: number;
-
- /**
- * Maximum number of tokens to generate in the completion.
- */
- maxOutputTokens?: number;
-
- /**
- * Top-p changes how the model selects tokens for output.
- *
- * Tokens are selected from most probable to least until the sum
- * of their probabilities equals the top-p value.
- *
- * For example, if tokens A, B, and C have a probability of
- * .3, .2, and .1 and the top-p value is .5, then the model will
- * select either A or B as the next token (using temperature).
- *
- * Note: The default value varies by model
- */
- topP?: number;
-
- /**
- * Top-k changes how the model selects tokens for output.
- *
- * A top-k of 1 means the selected token is the most probable among
- * all tokens in the model’s vocabulary (also called greedy decoding),
- * while a top-k of 3 means that the next token is selected from
- * among the 3 most probable tokens (using temperature).
- *
- * Note: The default value varies by model
- */
- topK?: number;
-
- /**
- * The set of character sequences (up to 5) that will stop output generation.
- * If specified, the API will stop at the first appearance of a stop
- * sequence.
- *
- * Note: The stop sequence will not be included as part of the response.
- */
- stopSequences?: string[];
-
- /**
- * A list of unique `SafetySetting` instances for blocking unsafe content. The API will block
- * any prompts and responses that fail to meet the thresholds set by these settings. If there
- * is no `SafetySetting` for a given `SafetyCategory` provided in the list, the API will use
- * the default safety setting for that category.
- */
- safetySettings?: protos.google.ai.generativelanguage.v1beta2.ISafetySetting[];
-
- /**
- * Google Palm API key to use
- */
- apiKey?: string;
-}
-
-/**
- * Google Palm 2 Language Model Wrapper to generate texts
- */
-export class GooglePaLM extends LLM implements GooglePaLMTextInput {
- get lc_secrets(): { [key: string]: string } | undefined {
- return {
- apiKey: "GOOGLE_PALM_API_KEY",
- };
- }
-
- modelName = "models/text-bison-001";
-
- temperature?: number; // default value chosen based on model
-
- maxOutputTokens?: number; // defaults to 64
-
- topP?: number; // default value chosen based on model
-
- topK?: number; // default value chosen based on model
-
- stopSequences: string[] = [];
-
- safetySettings?: protos.google.ai.generativelanguage.v1beta2.ISafetySetting[]; // default safety setting for that category
-
- apiKey?: string;
-
- private client: TextServiceClient;
-
- constructor(fields?: GooglePaLMTextInput) {
- super(fields ?? {});
-
- this.modelName = fields?.modelName ?? this.modelName;
-
- this.temperature = fields?.temperature ?? this.temperature;
- if (this.temperature && (this.temperature < 0 || this.temperature > 1)) {
- throw new Error("`temperature` must be in the range of [0.0,1.0]");
- }
-
- this.maxOutputTokens = fields?.maxOutputTokens ?? this.maxOutputTokens;
- if (this.maxOutputTokens && this.maxOutputTokens < 0) {
- throw new Error("`maxOutputTokens` must be a positive integer");
- }
-
- this.topP = fields?.topP ?? this.topP;
- if (this.topP && this.topP < 0) {
- throw new Error("`topP` must be a positive integer");
- }
-
- if (this.topP && this.topP > 1) {
- throw new Error("Google PaLM `topP` must in the range of [0,1]");
- }
-
- this.topK = fields?.topK ?? this.topK;
- if (this.topK && this.topK < 0) {
- throw new Error("`topK` must be a positive integer");
- }
-
- this.stopSequences = fields?.stopSequences ?? this.stopSequences;
-
- this.safetySettings = fields?.safetySettings ?? this.safetySettings;
- if (this.safetySettings && this.safetySettings.length > 0) {
- const safetySettingsSet = new Set(
- this.safetySettings.map((s) => s.category)
- );
- if (safetySettingsSet.size !== this.safetySettings.length) {
- throw new Error(
- "The categories in `safetySettings` array must be unique"
- );
- }
- }
-
- this.apiKey =
- fields?.apiKey ?? getEnvironmentVariable("GOOGLE_PALM_API_KEY");
- if (!this.apiKey) {
- throw new Error(
- "Please set an API key for Google Palm 2 in the environment variable GOOGLE_PALM_API_KEY or in the `apiKey` field of the GooglePalm constructor"
- );
- }
-
- this.client = new TextServiceClient({
- authClient: new GoogleAuth().fromAPIKey(this.apiKey),
- });
- }
-
- _llmType(): string {
- return "googlepalm";
- }
-
- async _call(
- prompt: string,
- options: this["ParsedCallOptions"]
- ): Promise {
- const res = await this.caller.callWithOptions(
- { signal: options.signal },
- this._generateText.bind(this),
- prompt
- );
- return res ?? "";
- }
-
- protected async _generateText(
- prompt: string
- ): Promise {
- const res = await this.client.generateText({
- model: this.modelName,
- temperature: this.temperature,
- candidateCount: 1,
- topK: this.topK,
- topP: this.topP,
- maxOutputTokens: this.maxOutputTokens,
- stopSequences: this.stopSequences,
- safetySettings: this.safetySettings,
- prompt: {
- text: prompt,
- },
- });
- return res[0].candidates && res[0].candidates.length > 0
- ? res[0].candidates[0].output
- : undefined;
- }
-}
+export * from "@langchain/community/llms/googlepalm";
diff --git a/langchain/src/llms/googlevertexai/index.ts b/langchain/src/llms/googlevertexai/index.ts
index c3c7cbd6127a..0616e82bdd49 100644
--- a/langchain/src/llms/googlevertexai/index.ts
+++ b/langchain/src/llms/googlevertexai/index.ts
@@ -1,66 +1 @@
-import { GoogleAuthOptions } from "google-auth-library";
-import { GoogleVertexAILLMConnection } from "../../util/googlevertexai-connection.js";
-import { GoogleVertexAIBaseLLMInput } from "../../types/googlevertexai-types.js";
-import { BaseGoogleVertexAI } from "./common.js";
-import { GAuthClient } from "../../util/googlevertexai-gauth.js";
-
-/**
- * Interface representing the input to the Google Vertex AI model.
- */
-export interface GoogleVertexAITextInput
- extends GoogleVertexAIBaseLLMInput {}
-
-/**
- * Enables calls to the Google Cloud's Vertex AI API to access
- * Large Language Models.
- *
- * To use, you will need to have one of the following authentication
- * methods in place:
- * - You are logged into an account permitted to the Google Cloud project
- * using Vertex AI.
- * - You are running this on a machine using a service account permitted to
- * the Google Cloud project using Vertex AI.
- * - The `GOOGLE_APPLICATION_CREDENTIALS` environment variable is set to the
- * path of a credentials file for a service account permitted to the
- * Google Cloud project using Vertex AI.
- * @example
- * ```typescript
- * const model = new GoogleVertexAI({
- * temperature: 0.7,
- * });
- * const stream = await model.stream(
- * "What would be a good company name for a company that makes colorful socks?",
- * );
- * for await (const chunk of stream) {
- * console.log(chunk);
- * }
- * ```
- */
-export class GoogleVertexAI extends BaseGoogleVertexAI {
- static lc_name() {
- return "VertexAI";
- }
-
- constructor(fields?: GoogleVertexAITextInput) {
- super(fields);
-
- const client = new GAuthClient({
- scopes: "https://www.googleapis.com/auth/cloud-platform",
- ...fields?.authOptions,
- });
-
- this.connection = new GoogleVertexAILLMConnection(
- { ...fields, ...this },
- this.caller,
- client,
- false
- );
-
- this.streamedConnection = new GoogleVertexAILLMConnection(
- { ...fields, ...this },
- this.caller,
- client,
- true
- );
- }
-}
+export * from "@langchain/community/llms/googlevertexai";
diff --git a/langchain/src/llms/googlevertexai/web.ts b/langchain/src/llms/googlevertexai/web.ts
index 0b656308d53b..cecd871df86d 100644
--- a/langchain/src/llms/googlevertexai/web.ts
+++ b/langchain/src/llms/googlevertexai/web.ts
@@ -1,66 +1 @@
-import {
- WebGoogleAuth,
- WebGoogleAuthOptions,
-} from "../../util/googlevertexai-webauth.js";
-import { GoogleVertexAILLMConnection } from "../../util/googlevertexai-connection.js";
-import { GoogleVertexAIBaseLLMInput } from "../../types/googlevertexai-types.js";
-import { BaseGoogleVertexAI } from "./common.js";
-
-/**
- * Interface representing the input to the Google Vertex AI model.
- */
-export interface GoogleVertexAITextInput
- extends GoogleVertexAIBaseLLMInput {}
-
-/**
- * Enables calls to the Google Cloud's Vertex AI API to access
- * Large Language Models.
- *
- * This entrypoint and class are intended to be used in web environments like Edge
- * functions where you do not have access to the file system. It supports passing
- * service account credentials directly as a "GOOGLE_VERTEX_AI_WEB_CREDENTIALS"
- * environment variable or directly as "authOptions.credentials".
- * @example
- * ```typescript
- * const model = new GoogleVertexAI({
- * temperature: 0.7,
- * });
- * const stream = await model.stream(
- * "What would be a good company name for a company that makes colorful socks?",
- * );
- * for await (const chunk of stream) {
- * console.log(chunk);
- * }
- * ```
- */
-export class GoogleVertexAI extends BaseGoogleVertexAI {
- static lc_name() {
- return "VertexAI";
- }
-
- get lc_secrets(): { [key: string]: string } {
- return {
- "authOptions.credentials": "GOOGLE_VERTEX_AI_WEB_CREDENTIALS",
- };
- }
-
- constructor(fields?: GoogleVertexAITextInput) {
- super(fields);
-
- const client = new WebGoogleAuth(fields?.authOptions);
-
- this.connection = new GoogleVertexAILLMConnection(
- { ...fields, ...this },
- this.caller,
- client,
- false
- );
-
- this.streamedConnection = new GoogleVertexAILLMConnection(
- { ...fields, ...this },
- this.caller,
- client,
- true
- );
- }
-}
+export * from "@langchain/community/llms/googlevertexai/web";
diff --git a/langchain/src/llms/gradient_ai.ts b/langchain/src/llms/gradient_ai.ts
index 782bb8cd114e..f6a15989551a 100644
--- a/langchain/src/llms/gradient_ai.ts
+++ b/langchain/src/llms/gradient_ai.ts
@@ -1,136 +1 @@
-import { Gradient } from "@gradientai/nodejs-sdk";
-import { BaseLLMCallOptions, BaseLLMParams, LLM } from "./base.js";
-import { getEnvironmentVariable } from "../util/env.js";
-
-/**
- * The GradientLLMParams interface defines the input parameters for
- * the GradientLLM class.
- */
-export interface GradientLLMParams extends BaseLLMParams {
- /**
- * Gradient AI Access Token.
- * Provide Access Token if you do not wish to automatically pull from env.
- */
- gradientAccessKey?: string;
- /**
- * Gradient Workspace Id.
- * Provide workspace id if you do not wish to automatically pull from env.
- */
- workspaceId?: string;
- /**
- * Parameters accepted by the Gradient npm package.
- */
- inferenceParameters?: Record;
- /**
- * Gradient AI Model Slug.
- */
- modelSlug?: string;
- /**
- * Gradient Adapter ID for custom fine tuned models.
- */
- adapterId?: string;
-}
-
-/**
- * The GradientLLM class is used to interact with Gradient AI inference Endpoint models.
- * This requires your Gradient AI Access Token which is autoloaded if not specified.
- */
-export class GradientLLM extends LLM {
- static lc_name() {
- return "GradientLLM";
- }
-
- get lc_secrets(): { [key: string]: string } | undefined {
- return {
- gradientAccessKey: "GRADIENT_ACCESS_TOKEN",
- workspaceId: "GRADIENT_WORKSPACE_ID",
- };
- }
-
- modelSlug = "llama2-7b-chat";
-
- adapterId?: string;
-
- gradientAccessKey?: string;
-
- workspaceId?: string;
-
- inferenceParameters?: Record;
-
- // Gradient AI does not export the BaseModel type. Once it does, we can use it here.
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- model: any;
-
- constructor(fields: GradientLLMParams) {
- super(fields);
-
- this.modelSlug = fields?.modelSlug ?? this.modelSlug;
- this.adapterId = fields?.adapterId;
- this.gradientAccessKey =
- fields?.gradientAccessKey ??
- getEnvironmentVariable("GRADIENT_ACCESS_TOKEN");
- this.workspaceId =
- fields?.workspaceId ?? getEnvironmentVariable("GRADIENT_WORKSPACE_ID");
-
- this.inferenceParameters = fields.inferenceParameters;
-
- if (!this.gradientAccessKey) {
- throw new Error("Missing Gradient AI Access Token");
- }
-
- if (!this.workspaceId) {
- throw new Error("Missing Gradient AI Workspace ID");
- }
- }
-
- _llmType() {
- return "gradient_ai";
- }
-
- /**
- * Calls the Gradient AI endpoint and retrieves the result.
- * @param {string} prompt The input prompt.
- * @returns {Promise} A promise that resolves to the generated string.
- */
- /** @ignore */
- async _call(
- prompt: string,
- _options: this["ParsedCallOptions"]
- ): Promise {
- await this.setModel();
-
- // GradientLLM does not export the CompleteResponse type. Once it does, we can use it here.
- interface CompleteResponse {
- finishReason: string;
- generatedOutput: string;
- }
-
- const response = (await this.caller.call(async () =>
- this.model.complete({
- query: prompt,
- ...this.inferenceParameters,
- })
- )) as CompleteResponse;
-
- return response.generatedOutput;
- }
-
- async setModel() {
- if (this.model) return;
-
- const gradient = new Gradient({
- accessToken: this.gradientAccessKey,
- workspaceId: this.workspaceId,
- });
-
- if (this.adapterId) {
- this.model = await gradient.getModelAdapter({
- modelAdapterId: this.adapterId,
- });
- } else {
- this.model = await gradient.getBaseModel({
- baseModelSlug: this.modelSlug,
- });
- }
- }
-}
+export * from "@langchain/community/llms/gradient_ai";
diff --git a/langchain/src/llms/hf.ts b/langchain/src/llms/hf.ts
index e849a7acb37e..2f0e767bf6cd 100644
--- a/langchain/src/llms/hf.ts
+++ b/langchain/src/llms/hf.ts
@@ -1,155 +1 @@
-import { getEnvironmentVariable } from "../util/env.js";
-import { LLM, BaseLLMParams } from "./base.js";
-
-/**
- * Interface defining the parameters for configuring the Hugging Face
- * model for text generation.
- */
-export interface HFInput {
- /** Model to use */
- model: string;
-
- /** Custom inference endpoint URL to use */
- endpointUrl?: string;
-
- /** Sampling temperature to use */
- temperature?: number;
-
- /**
- * Maximum number of tokens to generate in the completion.
- */
- maxTokens?: number;
-
- /** Total probability mass of tokens to consider at each step */
- topP?: number;
-
- /** Integer to define the top tokens considered within the sample operation to create new text. */
- topK?: number;
-
- /** Penalizes repeated tokens according to frequency */
- frequencyPenalty?: number;
-
- /** API key to use. */
- apiKey?: string;
-
- /**
- * Credentials to use for the request. If this is a string, it will be passed straight on. If it's a boolean, true will be "include" and false will not send credentials at all.
- */
- includeCredentials?: string | boolean;
-}
-
-/**
- * Class implementing the Large Language Model (LLM) interface using the
- * Hugging Face Inference API for text generation.
- * @example
- * ```typescript
- * const model = new HuggingFaceInference({
- * model: "gpt2",
- * temperature: 0.7,
- * maxTokens: 50,
- * });
- *
- * const res = await model.call(
- * "Question: What would be a good company name for a company that makes colorful socks?\nAnswer:"
- * );
- * console.log({ res });
- * ```
- */
-export class HuggingFaceInference extends LLM implements HFInput {
- get lc_secrets(): { [key: string]: string } | undefined {
- return {
- apiKey: "HUGGINGFACEHUB_API_KEY",
- };
- }
-
- model = "gpt2";
-
- temperature: number | undefined = undefined;
-
- maxTokens: number | undefined = undefined;
-
- topP: number | undefined = undefined;
-
- topK: number | undefined = undefined;
-
- frequencyPenalty: number | undefined = undefined;
-
- apiKey: string | undefined = undefined;
-
- endpointUrl: string | undefined = undefined;
-
- includeCredentials: string | boolean | undefined = undefined;
-
- constructor(fields?: Partial & BaseLLMParams) {
- super(fields ?? {});
-
- this.model = fields?.model ?? this.model;
- this.temperature = fields?.temperature ?? this.temperature;
- this.maxTokens = fields?.maxTokens ?? this.maxTokens;
- this.topP = fields?.topP ?? this.topP;
- this.topK = fields?.topK ?? this.topK;
- this.frequencyPenalty = fields?.frequencyPenalty ?? this.frequencyPenalty;
- this.apiKey =
- fields?.apiKey ?? getEnvironmentVariable("HUGGINGFACEHUB_API_KEY");
- this.endpointUrl = fields?.endpointUrl;
- this.includeCredentials = fields?.includeCredentials;
-
- if (!this.apiKey) {
- throw new Error(
- "Please set an API key for HuggingFace Hub in the environment variable HUGGINGFACEHUB_API_KEY or in the apiKey field of the HuggingFaceInference constructor."
- );
- }
- }
-
- _llmType() {
- return "hf";
- }
-
- /** @ignore */
- async _call(
- prompt: string,
- options: this["ParsedCallOptions"]
- ): Promise {
- const { HfInference } = await HuggingFaceInference.imports();
- const hf = this.endpointUrl
- ? new HfInference(this.apiKey, {
- includeCredentials: this.includeCredentials,
- }).endpoint(this.endpointUrl)
- : new HfInference(this.apiKey, {
- includeCredentials: this.includeCredentials,
- });
-
- const res = await this.caller.callWithOptions(
- { signal: options.signal },
- hf.textGeneration.bind(hf),
- {
- model: this.model,
- parameters: {
- // make it behave similar to openai, returning only the generated text
- return_full_text: false,
- temperature: this.temperature,
- max_new_tokens: this.maxTokens,
- top_p: this.topP,
- top_k: this.topK,
- repetition_penalty: this.frequencyPenalty,
- },
- inputs: prompt,
- }
- );
- return res.generated_text;
- }
-
- /** @ignore */
- static async imports(): Promise<{
- HfInference: typeof import("@huggingface/inference").HfInference;
- }> {
- try {
- const { HfInference } = await import("@huggingface/inference");
- return { HfInference };
- } catch (e) {
- throw new Error(
- "Please install huggingface as a dependency with, e.g. `yarn add @huggingface/inference`"
- );
- }
- }
-}
+export * from "@langchain/community/llms/hf";
diff --git a/langchain/src/llms/llama_cpp.ts b/langchain/src/llms/llama_cpp.ts
index f2d6518ffd2b..ce09302c20d3 100644
--- a/langchain/src/llms/llama_cpp.ts
+++ b/langchain/src/llms/llama_cpp.ts
@@ -1,116 +1 @@
-import { LlamaModel, LlamaContext, LlamaChatSession } from "node-llama-cpp";
-import {
- LlamaBaseCppInputs,
- createLlamaModel,
- createLlamaContext,
- createLlamaSession,
-} from "../util/llama_cpp.js";
-import { LLM, BaseLLMCallOptions, BaseLLMParams } from "./base.js";
-import { CallbackManagerForLLMRun } from "../callbacks/manager.js";
-import { GenerationChunk } from "../schema/index.js";
-
-/**
- * Note that the modelPath is the only required parameter. For testing you
- * can set this in the environment variable `LLAMA_PATH`.
- */
-export interface LlamaCppInputs extends LlamaBaseCppInputs, BaseLLMParams {}
-
-export interface LlamaCppCallOptions extends BaseLLMCallOptions {
- /** The maximum number of tokens the response should contain. */
- maxTokens?: number;
- /** A function called when matching the provided token array */
- onToken?: (tokens: number[]) => void;
-}
-
-/**
- * To use this model you need to have the `node-llama-cpp` module installed.
- * This can be installed using `npm install -S node-llama-cpp` and the minimum
- * version supported in version 2.0.0.
- * This also requires that have a locally built version of Llama2 installed.
- */
-export class LlamaCpp extends LLM {
- declare CallOptions: LlamaCppCallOptions;
-
- static inputs: LlamaCppInputs;
-
- maxTokens?: number;
-
- temperature?: number;
-
- topK?: number;
-
- topP?: number;
-
- trimWhitespaceSuffix?: boolean;
-
- _model: LlamaModel;
-
- _context: LlamaContext;
-
- _session: LlamaChatSession;
-
- static lc_name() {
- return "LlamaCpp";
- }
-
- constructor(inputs: LlamaCppInputs) {
- super(inputs);
- this.maxTokens = inputs?.maxTokens;
- this.temperature = inputs?.temperature;
- this.topK = inputs?.topK;
- this.topP = inputs?.topP;
- this.trimWhitespaceSuffix = inputs?.trimWhitespaceSuffix;
- this._model = createLlamaModel(inputs);
- this._context = createLlamaContext(this._model, inputs);
- this._session = createLlamaSession(this._context);
- }
-
- _llmType() {
- return "llama2_cpp";
- }
-
- /** @ignore */
- async _call(
- prompt: string,
- options?: this["ParsedCallOptions"]
- ): Promise {
- try {
- const promptOptions = {
- onToken: options?.onToken,
- maxTokens: this?.maxTokens,
- temperature: this?.temperature,
- topK: this?.topK,
- topP: this?.topP,
- trimWhitespaceSuffix: this?.trimWhitespaceSuffix,
- };
- const completion = await this._session.prompt(prompt, promptOptions);
- return completion;
- } catch (e) {
- throw new Error("Error getting prompt completion.");
- }
- }
-
- async *_streamResponseChunks(
- prompt: string,
- _options: this["ParsedCallOptions"],
- runManager?: CallbackManagerForLLMRun
- ): AsyncGenerator {
- const promptOptions = {
- temperature: this?.temperature,
- topK: this?.topK,
- topP: this?.topP,
- };
-
- const stream = await this.caller.call(async () =>
- this._context.evaluate(this._context.encode(prompt), promptOptions)
- );
-
- for await (const chunk of stream) {
- yield new GenerationChunk({
- text: this._context.decode([chunk]),
- generationInfo: {},
- });
- await runManager?.handleLLMNewToken(this._context.decode([chunk]) ?? "");
- }
- }
-}
+export * from "@langchain/community/llms/llama_cpp";
diff --git a/langchain/src/llms/ollama.ts b/langchain/src/llms/ollama.ts
index 8b5c178cfb1f..1369ed4c0c60 100644
--- a/langchain/src/llms/ollama.ts
+++ b/langchain/src/llms/ollama.ts
@@ -1,245 +1 @@
-import { LLM, BaseLLMParams } from "./base.js";
-import {
- createOllamaStream,
- OllamaInput,
- OllamaCallOptions,
-} from "../util/ollama.js";
-import { CallbackManagerForLLMRun } from "../callbacks/manager.js";
-import { GenerationChunk } from "../schema/index.js";
-import type { StringWithAutocomplete } from "../util/types.js";
-
-/**
- * Class that represents the Ollama language model. It extends the base
- * LLM class and implements the OllamaInput interface.
- * @example
- * ```typescript
- * const ollama = new Ollama({
- * baseUrl: "http://api.example.com",
- * model: "llama2",
- * });
- *
- * // Streaming translation from English to German
- * const stream = await ollama.stream(
- * `Translate "I love programming" into German.`
- * );
- *
- * const chunks = [];
- * for await (const chunk of stream) {
- * chunks.push(chunk);
- * }
- *
- * console.log(chunks.join(""));
- * ```
- */
-export class Ollama extends LLM implements OllamaInput {
- static lc_name() {
- return "Ollama";
- }
-
- lc_serializable = true;
-
- model = "llama2";
-
- baseUrl = "http://localhost:11434";
-
- embeddingOnly?: boolean;
-
- f16KV?: boolean;
-
- frequencyPenalty?: number;
-
- logitsAll?: boolean;
-
- lowVram?: boolean;
-
- mainGpu?: number;
-
- mirostat?: number;
-
- mirostatEta?: number;
-
- mirostatTau?: number;
-
- numBatch?: number;
-
- numCtx?: number;
-
- numGpu?: number;
-
- numGqa?: number;
-
- numKeep?: number;
-
- numThread?: number;
-
- penalizeNewline?: boolean;
-
- presencePenalty?: number;
-
- repeatLastN?: number;
-
- repeatPenalty?: number;
-
- ropeFrequencyBase?: number;
-
- ropeFrequencyScale?: number;
-
- temperature?: number;
-
- stop?: string[];
-
- tfsZ?: number;
-
- topK?: number;
-
- topP?: number;
-
- typicalP?: number;
-
- useMLock?: boolean;
-
- useMMap?: boolean;
-
- vocabOnly?: boolean;
-
- format?: StringWithAutocomplete<"json">;
-
- constructor(fields: OllamaInput & BaseLLMParams) {
- super(fields);
- this.model = fields.model ?? this.model;
- this.baseUrl = fields.baseUrl?.endsWith("/")
- ? fields.baseUrl.slice(0, -1)
- : fields.baseUrl ?? this.baseUrl;
-
- this.embeddingOnly = fields.embeddingOnly;
- this.f16KV = fields.f16KV;
- this.frequencyPenalty = fields.frequencyPenalty;
- this.logitsAll = fields.logitsAll;
- this.lowVram = fields.lowVram;
- this.mainGpu = fields.mainGpu;
- this.mirostat = fields.mirostat;
- this.mirostatEta = fields.mirostatEta;
- this.mirostatTau = fields.mirostatTau;
- this.numBatch = fields.numBatch;
- this.numCtx = fields.numCtx;
- this.numGpu = fields.numGpu;
- this.numGqa = fields.numGqa;
- this.numKeep = fields.numKeep;
- this.numThread = fields.numThread;
- this.penalizeNewline = fields.penalizeNewline;
- this.presencePenalty = fields.presencePenalty;
- this.repeatLastN = fields.repeatLastN;
- this.repeatPenalty = fields.repeatPenalty;
- this.ropeFrequencyBase = fields.ropeFrequencyBase;
- this.ropeFrequencyScale = fields.ropeFrequencyScale;
- this.temperature = fields.temperature;
- this.stop = fields.stop;
- this.tfsZ = fields.tfsZ;
- this.topK = fields.topK;
- this.topP = fields.topP;
- this.typicalP = fields.typicalP;
- this.useMLock = fields.useMLock;
- this.useMMap = fields.useMMap;
- this.vocabOnly = fields.vocabOnly;
- this.format = fields.format;
- }
-
- _llmType() {
- return "ollama";
- }
-
- invocationParams(options?: this["ParsedCallOptions"]) {
- return {
- model: this.model,
- format: this.format,
- options: {
- embedding_only: this.embeddingOnly,
- f16_kv: this.f16KV,
- frequency_penalty: this.frequencyPenalty,
- logits_all: this.logitsAll,
- low_vram: this.lowVram,
- main_gpu: this.mainGpu,
- mirostat: this.mirostat,
- mirostat_eta: this.mirostatEta,
- mirostat_tau: this.mirostatTau,
- num_batch: this.numBatch,
- num_ctx: this.numCtx,
- num_gpu: this.numGpu,
- num_gqa: this.numGqa,
- num_keep: this.numKeep,
- num_thread: this.numThread,
- penalize_newline: this.penalizeNewline,
- presence_penalty: this.presencePenalty,
- repeat_last_n: this.repeatLastN,
- repeat_penalty: this.repeatPenalty,
- rope_frequency_base: this.ropeFrequencyBase,
- rope_frequency_scale: this.ropeFrequencyScale,
- temperature: this.temperature,
- stop: options?.stop ?? this.stop,
- tfs_z: this.tfsZ,
- top_k: this.topK,
- top_p: this.topP,
- typical_p: this.typicalP,
- use_mlock: this.useMLock,
- use_mmap: this.useMMap,
- vocab_only: this.vocabOnly,
- },
- };
- }
-
- async *_streamResponseChunks(
- prompt: string,
- options: this["ParsedCallOptions"],
- runManager?: CallbackManagerForLLMRun
- ): AsyncGenerator {
- const stream = await this.caller.call(async () =>
- createOllamaStream(
- this.baseUrl,
- { ...this.invocationParams(options), prompt },
- options
- )
- );
- for await (const chunk of stream) {
- if (!chunk.done) {
- yield new GenerationChunk({
- text: chunk.response,
- generationInfo: {
- ...chunk,
- response: undefined,
- },
- });
- await runManager?.handleLLMNewToken(chunk.response ?? "");
- } else {
- yield new GenerationChunk({
- text: "",
- generationInfo: {
- model: chunk.model,
- total_duration: chunk.total_duration,
- load_duration: chunk.load_duration,
- prompt_eval_count: chunk.prompt_eval_count,
- prompt_eval_duration: chunk.prompt_eval_duration,
- eval_count: chunk.eval_count,
- eval_duration: chunk.eval_duration,
- },
- });
- }
- }
- }
-
- /** @ignore */
- async _call(
- prompt: string,
- options: this["ParsedCallOptions"],
- runManager?: CallbackManagerForLLMRun
- ): Promise {
- const chunks = [];
- for await (const chunk of this._streamResponseChunks(
- prompt,
- options,
- runManager
- )) {
- chunks.push(chunk.text);
- }
- return chunks.join("");
- }
-}
+export * from "@langchain/community/llms/ollama";
diff --git a/langchain/src/llms/openai-chat.ts b/langchain/src/llms/openai-chat.ts
index 4077a5efde89..06cb7faf0f1d 100644
--- a/langchain/src/llms/openai-chat.ts
+++ b/langchain/src/llms/openai-chat.ts
@@ -1,471 +1,18 @@
-import { type ClientOptions, OpenAI as OpenAIClient } from "openai";
+import { OpenAIChat } from "@langchain/openai";
+
import { CallbackManagerForLLMRun } from "../callbacks/manager.js";
-import { Generation, GenerationChunk, LLMResult } from "../schema/index.js";
-import {
- AzureOpenAIInput,
- OpenAICallOptions,
- OpenAIChatInput,
- OpenAICoreRequestOptions,
- LegacyOpenAIInput,
-} from "../types/openai-types.js";
-import { OpenAIEndpointConfig, getEndpoint } from "../util/azure.js";
+import type { Generation, LLMResult } from "../schema/index.js";
import { getEnvironmentVariable } from "../util/env.js";
import { promptLayerTrackRequest } from "../util/prompt-layer.js";
-import { BaseLLMParams, LLM } from "./base.js";
-import { wrapOpenAIClientError } from "../util/openai.js";
-
-export { type AzureOpenAIInput, type OpenAIChatInput };
-/**
- * Interface that extends the OpenAICallOptions interface and includes an
- * optional promptIndex property. It represents the options that can be
- * passed when making a call to the OpenAI Chat API.
- */
-export interface OpenAIChatCallOptions extends OpenAICallOptions {
- promptIndex?: number;
-}
-
-/**
- * Wrapper around OpenAI large language models that use the Chat endpoint.
- *
- * To use you should have the `openai` package installed, with the
- * `OPENAI_API_KEY` environment variable set.
- *
- * To use with Azure you should have the `openai` package installed, with the
- * `AZURE_OPENAI_API_KEY`,
- * `AZURE_OPENAI_API_INSTANCE_NAME`,
- * `AZURE_OPENAI_API_DEPLOYMENT_NAME`
- * and `AZURE_OPENAI_API_VERSION` environment variable set.
- *
- * @remarks
- * Any parameters that are valid to be passed to {@link
- * https://platform.openai.com/docs/api-reference/chat/create |
- * `openai.createCompletion`} can be passed through {@link modelKwargs}, even
- * if not explicitly available on this class.
- *
- * @augments BaseLLM
- * @augments OpenAIInput
- * @augments AzureOpenAIChatInput
- * @example
- * ```typescript
- * const model = new OpenAIChat({
- * prefixMessages: [
- * {
- * role: "system",
- * content: "You are a helpful assistant that answers in pirate language",
- * },
- * ],
- * maxTokens: 50,
- * });
- *
- * const res = await model.call(
- * "What would be a good company name for a company that makes colorful socks?"
- * );
- * console.log({ res });
- * ```
- */
-export class OpenAIChat
- extends LLM
- implements OpenAIChatInput, AzureOpenAIInput
-{
- static lc_name() {
- return "OpenAIChat";
- }
-
- get callKeys() {
- return [...super.callKeys, "options", "promptIndex"];
- }
-
- lc_serializable = true;
-
- get lc_secrets(): { [key: string]: string } | undefined {
- return {
- openAIApiKey: "OPENAI_API_KEY",
- azureOpenAIApiKey: "AZURE_OPENAI_API_KEY",
- organization: "OPENAI_ORGANIZATION",
- };
- }
-
- get lc_aliases(): Record {
- return {
- modelName: "model",
- openAIApiKey: "openai_api_key",
- azureOpenAIApiVersion: "azure_openai_api_version",
- azureOpenAIApiKey: "azure_openai_api_key",
- azureOpenAIApiInstanceName: "azure_openai_api_instance_name",
- azureOpenAIApiDeploymentName: "azure_openai_api_deployment_name",
- };
- }
-
- temperature = 1;
-
- topP = 1;
-
- frequencyPenalty = 0;
-
- presencePenalty = 0;
-
- n = 1;
-
- logitBias?: Record;
-
- maxTokens?: number;
-
- modelName = "gpt-3.5-turbo";
-
- prefixMessages?: OpenAIClient.Chat.ChatCompletionMessageParam[];
-
- modelKwargs?: OpenAIChatInput["modelKwargs"];
-
- timeout?: number;
-
- stop?: string[];
-
- user?: string;
-
- streaming = false;
-
- openAIApiKey?: string;
-
- azureOpenAIApiVersion?: string;
-
- azureOpenAIApiKey?: string;
-
- azureOpenAIApiInstanceName?: string;
-
- azureOpenAIApiDeploymentName?: string;
-
- azureOpenAIBasePath?: string;
-
- organization?: string;
-
- private client: OpenAIClient;
-
- private clientConfig: ClientOptions;
-
- constructor(
- fields?: Partial &
- Partial &
- BaseLLMParams & {
- configuration?: ClientOptions & LegacyOpenAIInput;
- },
- /** @deprecated */
- configuration?: ClientOptions & LegacyOpenAIInput
- ) {
- super(fields ?? {});
-
- this.openAIApiKey =
- fields?.openAIApiKey ?? getEnvironmentVariable("OPENAI_API_KEY");
-
- this.azureOpenAIApiKey =
- fields?.azureOpenAIApiKey ??
- getEnvironmentVariable("AZURE_OPENAI_API_KEY");
-
- if (!this.azureOpenAIApiKey && !this.openAIApiKey) {
- throw new Error("OpenAI or Azure OpenAI API key not found");
- }
-
- this.azureOpenAIApiInstanceName =
- fields?.azureOpenAIApiInstanceName ??
- getEnvironmentVariable("AZURE_OPENAI_API_INSTANCE_NAME");
-
- this.azureOpenAIApiDeploymentName =
- (fields?.azureOpenAIApiCompletionsDeploymentName ||
- fields?.azureOpenAIApiDeploymentName) ??
- (getEnvironmentVariable("AZURE_OPENAI_API_COMPLETIONS_DEPLOYMENT_NAME") ||
- getEnvironmentVariable("AZURE_OPENAI_API_DEPLOYMENT_NAME"));
-
- this.azureOpenAIApiVersion =
- fields?.azureOpenAIApiVersion ??
- getEnvironmentVariable("AZURE_OPENAI_API_VERSION");
-
- this.azureOpenAIBasePath =
- fields?.azureOpenAIBasePath ??
- getEnvironmentVariable("AZURE_OPENAI_BASE_PATH");
- this.organization =
- fields?.configuration?.organization ??
- getEnvironmentVariable("OPENAI_ORGANIZATION");
+export {
+ type AzureOpenAIInput,
+ type OpenAICallOptions,
+ type OpenAIInput,
+ type OpenAIChatCallOptions,
+} from "@langchain/openai";
- this.modelName = fields?.modelName ?? this.modelName;
- this.prefixMessages = fields?.prefixMessages ?? this.prefixMessages;
- this.modelKwargs = fields?.modelKwargs ?? {};
- this.timeout = fields?.timeout;
-
- this.temperature = fields?.temperature ?? this.temperature;
- this.topP = fields?.topP ?? this.topP;
- this.frequencyPenalty = fields?.frequencyPenalty ?? this.frequencyPenalty;
- this.presencePenalty = fields?.presencePenalty ?? this.presencePenalty;
- this.n = fields?.n ?? this.n;
- this.logitBias = fields?.logitBias;
- this.maxTokens = fields?.maxTokens;
- this.stop = fields?.stop;
- this.user = fields?.user;
-
- this.streaming = fields?.streaming ?? false;
-
- if (this.n > 1) {
- throw new Error(
- "Cannot use n > 1 in OpenAIChat LLM. Use ChatOpenAI Chat Model instead."
- );
- }
-
- if (this.azureOpenAIApiKey) {
- if (!this.azureOpenAIApiInstanceName && !this.azureOpenAIBasePath) {
- throw new Error("Azure OpenAI API instance name not found");
- }
- if (!this.azureOpenAIApiDeploymentName) {
- throw new Error("Azure OpenAI API deployment name not found");
- }
- if (!this.azureOpenAIApiVersion) {
- throw new Error("Azure OpenAI API version not found");
- }
- this.openAIApiKey = this.openAIApiKey ?? "";
- }
-
- this.clientConfig = {
- apiKey: this.openAIApiKey,
- organization: this.organization,
- baseURL: configuration?.basePath ?? fields?.configuration?.basePath,
- dangerouslyAllowBrowser: true,
- defaultHeaders:
- configuration?.baseOptions?.headers ??
- fields?.configuration?.baseOptions?.headers,
- defaultQuery:
- configuration?.baseOptions?.params ??
- fields?.configuration?.baseOptions?.params,
- ...configuration,
- ...fields?.configuration,
- };
- }
-
- /**
- * Get the parameters used to invoke the model
- */
- invocationParams(
- options?: this["ParsedCallOptions"]
- ): Omit {
- return {
- model: this.modelName,
- temperature: this.temperature,
- top_p: this.topP,
- frequency_penalty: this.frequencyPenalty,
- presence_penalty: this.presencePenalty,
- n: this.n,
- logit_bias: this.logitBias,
- max_tokens: this.maxTokens === -1 ? undefined : this.maxTokens,
- stop: options?.stop ?? this.stop,
- user: this.user,
- stream: this.streaming,
- ...this.modelKwargs,
- };
- }
-
- /** @ignore */
- _identifyingParams(): Omit<
- OpenAIClient.Chat.ChatCompletionCreateParams,
- "messages"
- > & {
- model_name: string;
- } & ClientOptions {
- return {
- model_name: this.modelName,
- ...this.invocationParams(),
- ...this.clientConfig,
- };
- }
-
- /**
- * Get the identifying parameters for the model
- */
- identifyingParams(): Omit<
- OpenAIClient.Chat.ChatCompletionCreateParams,
- "messages"
- > & {
- model_name: string;
- } & ClientOptions {
- return {
- model_name: this.modelName,
- ...this.invocationParams(),
- ...this.clientConfig,
- };
- }
-
- /**
- * Formats the messages for the OpenAI API.
- * @param prompt The prompt to be formatted.
- * @returns Array of formatted messages.
- */
- private formatMessages(
- prompt: string
- ): OpenAIClient.Chat.ChatCompletionMessageParam[] {
- const message: OpenAIClient.Chat.ChatCompletionMessageParam = {
- role: "user",
- content: prompt,
- };
- return this.prefixMessages ? [...this.prefixMessages, message] : [message];
- }
-
- async *_streamResponseChunks(
- prompt: string,
- options: this["ParsedCallOptions"],
- runManager?: CallbackManagerForLLMRun
- ): AsyncGenerator {
- const params = {
- ...this.invocationParams(options),
- messages: this.formatMessages(prompt),
- stream: true as const,
- };
- const stream = await this.completionWithRetry(params, options);
- for await (const data of stream) {
- const choice = data?.choices[0];
- if (!choice) {
- continue;
- }
- const { delta } = choice;
- const generationChunk = new GenerationChunk({
- text: delta.content ?? "",
- });
- yield generationChunk;
- const newTokenIndices = {
- prompt: options.promptIndex ?? 0,
- completion: choice.index ?? 0,
- };
- // eslint-disable-next-line no-void
- void runManager?.handleLLMNewToken(
- generationChunk.text ?? "",
- newTokenIndices
- );
- }
- if (options.signal?.aborted) {
- throw new Error("AbortError");
- }
- }
-
- /** @ignore */
- async _call(
- prompt: string,
- options: this["ParsedCallOptions"],
- runManager?: CallbackManagerForLLMRun
- ): Promise {
- const params = this.invocationParams(options);
-
- if (params.stream) {
- const stream = await this._streamResponseChunks(
- prompt,
- options,
- runManager
- );
- let finalChunk: GenerationChunk | undefined;
- for await (const chunk of stream) {
- if (finalChunk === undefined) {
- finalChunk = chunk;
- } else {
- finalChunk = finalChunk.concat(chunk);
- }
- }
- return finalChunk?.text ?? "";
- } else {
- const response = await this.completionWithRetry(
- {
- ...params,
- stream: false,
- messages: this.formatMessages(prompt),
- },
- {
- signal: options.signal,
- ...options.options,
- }
- );
- return response?.choices[0]?.message?.content ?? "";
- }
- }
-
- /**
- * Calls the OpenAI API with retry logic in case of failures.
- * @param request The request to send to the OpenAI API.
- * @param options Optional configuration for the API call.
- * @returns The response from the OpenAI API.
- */
- async completionWithRetry(
- request: OpenAIClient.Chat.ChatCompletionCreateParamsStreaming,
- options?: OpenAICoreRequestOptions
- ): Promise>;
-
- async completionWithRetry(
- request: OpenAIClient.Chat.ChatCompletionCreateParamsNonStreaming,
- options?: OpenAICoreRequestOptions
- ): Promise;
-
- async completionWithRetry(
- request:
- | OpenAIClient.Chat.ChatCompletionCreateParamsStreaming
- | OpenAIClient.Chat.ChatCompletionCreateParamsNonStreaming,
- options?: OpenAICoreRequestOptions
- ): Promise<
- | AsyncIterable
- | OpenAIClient.Chat.Completions.ChatCompletion
- > {
- const requestOptions = this._getClientOptions(options);
- return this.caller.call(async () => {
- try {
- const res = await this.client.chat.completions.create(
- request,
- requestOptions
- );
- return res;
- } catch (e) {
- const error = wrapOpenAIClientError(e);
- throw error;
- }
- });
- }
-
- /** @ignore */
- private _getClientOptions(options: OpenAICoreRequestOptions | undefined) {
- if (!this.client) {
- const openAIEndpointConfig: OpenAIEndpointConfig = {
- azureOpenAIApiDeploymentName: this.azureOpenAIApiDeploymentName,
- azureOpenAIApiInstanceName: this.azureOpenAIApiInstanceName,
- azureOpenAIApiKey: this.azureOpenAIApiKey,
- azureOpenAIBasePath: this.azureOpenAIBasePath,
- baseURL: this.clientConfig.baseURL,
- };
-
- const endpoint = getEndpoint(openAIEndpointConfig);
-
- const params = {
- ...this.clientConfig,
- baseURL: endpoint,
- timeout: this.timeout,
- maxRetries: 0,
- };
- if (!params.baseURL) {
- delete params.baseURL;
- }
-
- this.client = new OpenAIClient(params);
- }
- const requestOptions = {
- ...this.clientConfig,
- ...options,
- } as OpenAICoreRequestOptions;
- if (this.azureOpenAIApiKey) {
- requestOptions.headers = {
- "api-key": this.azureOpenAIApiKey,
- ...requestOptions.headers,
- };
- requestOptions.query = {
- "api-version": this.azureOpenAIApiVersion,
- ...requestOptions.query,
- };
- }
- return requestOptions;
- }
-
- _llmType() {
- return "openai";
- }
-}
+export { OpenAIChat };
/**
* PromptLayer wrapper to OpenAIChat
diff --git a/langchain/src/llms/openai.ts b/langchain/src/llms/openai.ts
index c962f30c096f..edfb429272b5 100644
--- a/langchain/src/llms/openai.ts
+++ b/langchain/src/llms/openai.ts
@@ -1,558 +1,17 @@
-import type { TiktokenModel } from "js-tiktoken/lite";
-import { type ClientOptions, OpenAI as OpenAIClient } from "openai";
-import { calculateMaxTokens } from "../base_language/count_tokens.js";
+import { OpenAI } from "@langchain/openai";
+
import { CallbackManagerForLLMRun } from "../callbacks/manager.js";
-import { GenerationChunk, LLMResult } from "../schema/index.js";
-import {
- AzureOpenAIInput,
- OpenAICallOptions,
- OpenAICoreRequestOptions,
- OpenAIInput,
- LegacyOpenAIInput,
-} from "../types/openai-types.js";
-import { OpenAIEndpointConfig, getEndpoint } from "../util/azure.js";
-import { chunkArray } from "../util/chunk.js";
+import type { LLMResult } from "../schema/index.js";
import { getEnvironmentVariable } from "../util/env.js";
import { promptLayerTrackRequest } from "../util/prompt-layer.js";
-import { BaseLLM, BaseLLMParams } from "./base.js";
-import { OpenAIChat } from "./openai-chat.js";
-import { wrapOpenAIClientError } from "../util/openai.js";
-
-export type { AzureOpenAIInput, OpenAICallOptions, OpenAIInput };
-
-/**
- * Interface for tracking token usage in OpenAI calls.
- */
-interface TokenUsage {
- completionTokens?: number;
- promptTokens?: number;
- totalTokens?: number;
-}
-
-/**
- * Wrapper around OpenAI large language models.
- *
- * To use you should have the `openai` package installed, with the
- * `OPENAI_API_KEY` environment variable set.
- *
- * To use with Azure you should have the `openai` package installed, with the
- * `AZURE_OPENAI_API_KEY`,
- * `AZURE_OPENAI_API_INSTANCE_NAME`,
- * `AZURE_OPENAI_API_DEPLOYMENT_NAME`
- * and `AZURE_OPENAI_API_VERSION` environment variable set.
- *
- * @remarks
- * Any parameters that are valid to be passed to {@link
- * https://platform.openai.com/docs/api-reference/completions/create |
- * `openai.createCompletion`} can be passed through {@link modelKwargs}, even
- * if not explicitly available on this class.
- * @example
- * ```typescript
- * const model = new OpenAI({
- * modelName: "gpt-4",
- * temperature: 0.7,
- * maxTokens: 1000,
- * maxRetries: 5,
- * });
- *
- * const res = await model.call(
- * "Question: What would be a good company name for a company that makes colorful socks?\nAnswer:"
- * );
- * console.log({ res });
- * ```
- */
-export class OpenAI
- extends BaseLLM
- implements OpenAIInput, AzureOpenAIInput
-{
- static lc_name() {
- return "OpenAI";
- }
-
- get callKeys() {
- return [...super.callKeys, "options"];
- }
-
- lc_serializable = true;
-
- get lc_secrets(): { [key: string]: string } | undefined {
- return {
- openAIApiKey: "OPENAI_API_KEY",
- azureOpenAIApiKey: "AZURE_OPENAI_API_KEY",
- organization: "OPENAI_ORGANIZATION",
- };
- }
-
- get lc_aliases(): Record {
- return {
- modelName: "model",
- openAIApiKey: "openai_api_key",
- azureOpenAIApiVersion: "azure_openai_api_version",
- azureOpenAIApiKey: "azure_openai_api_key",
- azureOpenAIApiInstanceName: "azure_openai_api_instance_name",
- azureOpenAIApiDeploymentName: "azure_openai_api_deployment_name",
- };
- }
-
- temperature = 0.7;
-
- maxTokens = 256;
-
- topP = 1;
-
- frequencyPenalty = 0;
-
- presencePenalty = 0;
-
- n = 1;
-
- bestOf?: number;
-
- logitBias?: Record;
-
- modelName = "gpt-3.5-turbo-instruct";
-
- modelKwargs?: OpenAIInput["modelKwargs"];
-
- batchSize = 20;
-
- timeout?: number;
- stop?: string[];
+export {
+ type AzureOpenAIInput,
+ type OpenAICallOptions,
+ type OpenAIInput,
+} from "@langchain/openai";
- user?: string;
-
- streaming = false;
-
- openAIApiKey?: string;
-
- azureOpenAIApiVersion?: string;
-
- azureOpenAIApiKey?: string;
-
- azureOpenAIApiInstanceName?: string;
-
- azureOpenAIApiDeploymentName?: string;
-
- azureOpenAIBasePath?: string;
-
- organization?: string;
-
- private client: OpenAIClient;
-
- private clientConfig: ClientOptions;
-
- constructor(
- fields?: Partial &
- Partial &
- BaseLLMParams & {
- configuration?: ClientOptions & LegacyOpenAIInput;
- },
- /** @deprecated */
- configuration?: ClientOptions & LegacyOpenAIInput
- ) {
- if (
- (fields?.modelName?.startsWith("gpt-3.5-turbo") ||
- fields?.modelName?.startsWith("gpt-4")) &&
- !fields?.modelName?.includes("-instruct")
- ) {
- // eslint-disable-next-line no-constructor-return
- return new OpenAIChat(
- fields,
- configuration
- ) as unknown as OpenAI;
- }
- super(fields ?? {});
-
- this.openAIApiKey =
- fields?.openAIApiKey ?? getEnvironmentVariable("OPENAI_API_KEY");
-
- this.azureOpenAIApiKey =
- fields?.azureOpenAIApiKey ??
- getEnvironmentVariable("AZURE_OPENAI_API_KEY");
-
- if (!this.azureOpenAIApiKey && !this.openAIApiKey) {
- throw new Error("OpenAI or Azure OpenAI API key not found");
- }
-
- this.azureOpenAIApiInstanceName =
- fields?.azureOpenAIApiInstanceName ??
- getEnvironmentVariable("AZURE_OPENAI_API_INSTANCE_NAME");
-
- this.azureOpenAIApiDeploymentName =
- (fields?.azureOpenAIApiCompletionsDeploymentName ||
- fields?.azureOpenAIApiDeploymentName) ??
- (getEnvironmentVariable("AZURE_OPENAI_API_COMPLETIONS_DEPLOYMENT_NAME") ||
- getEnvironmentVariable("AZURE_OPENAI_API_DEPLOYMENT_NAME"));
-
- this.azureOpenAIApiVersion =
- fields?.azureOpenAIApiVersion ??
- getEnvironmentVariable("AZURE_OPENAI_API_VERSION");
-
- this.azureOpenAIBasePath =
- fields?.azureOpenAIBasePath ??
- getEnvironmentVariable("AZURE_OPENAI_BASE_PATH");
-
- this.organization =
- fields?.configuration?.organization ??
- getEnvironmentVariable("OPENAI_ORGANIZATION");
-
- this.modelName = fields?.modelName ?? this.modelName;
- this.modelKwargs = fields?.modelKwargs ?? {};
- this.batchSize = fields?.batchSize ?? this.batchSize;
- this.timeout = fields?.timeout;
-
- this.temperature = fields?.temperature ?? this.temperature;
- this.maxTokens = fields?.maxTokens ?? this.maxTokens;
- this.topP = fields?.topP ?? this.topP;
- this.frequencyPenalty = fields?.frequencyPenalty ?? this.frequencyPenalty;
- this.presencePenalty = fields?.presencePenalty ?? this.presencePenalty;
- this.n = fields?.n ?? this.n;
- this.bestOf = fields?.bestOf ?? this.bestOf;
- this.logitBias = fields?.logitBias;
- this.stop = fields?.stop;
- this.user = fields?.user;
-
- this.streaming = fields?.streaming ?? false;
-
- if (this.streaming && this.bestOf && this.bestOf > 1) {
- throw new Error("Cannot stream results when bestOf > 1");
- }
-
- if (this.azureOpenAIApiKey) {
- if (!this.azureOpenAIApiInstanceName && !this.azureOpenAIBasePath) {
- throw new Error("Azure OpenAI API instance name not found");
- }
- if (!this.azureOpenAIApiDeploymentName) {
- throw new Error("Azure OpenAI API deployment name not found");
- }
- if (!this.azureOpenAIApiVersion) {
- throw new Error("Azure OpenAI API version not found");
- }
- this.openAIApiKey = this.openAIApiKey ?? "";
- }
-
- this.clientConfig = {
- apiKey: this.openAIApiKey,
- organization: this.organization,
- baseURL: configuration?.basePath ?? fields?.configuration?.basePath,
- dangerouslyAllowBrowser: true,
- defaultHeaders:
- configuration?.baseOptions?.headers ??
- fields?.configuration?.baseOptions?.headers,
- defaultQuery:
- configuration?.baseOptions?.params ??
- fields?.configuration?.baseOptions?.params,
- ...configuration,
- ...fields?.configuration,
- };
- }
-
- /**
- * Get the parameters used to invoke the model
- */
- invocationParams(
- options?: this["ParsedCallOptions"]
- ): Omit {
- return {
- model: this.modelName,
- temperature: this.temperature,
- max_tokens: this.maxTokens,
- top_p: this.topP,
- frequency_penalty: this.frequencyPenalty,
- presence_penalty: this.presencePenalty,
- n: this.n,
- best_of: this.bestOf,
- logit_bias: this.logitBias,
- stop: options?.stop ?? this.stop,
- user: this.user,
- stream: this.streaming,
- ...this.modelKwargs,
- };
- }
-
- /** @ignore */
- _identifyingParams(): Omit & {
- model_name: string;
- } & ClientOptions {
- return {
- model_name: this.modelName,
- ...this.invocationParams(),
- ...this.clientConfig,
- };
- }
-
- /**
- * Get the identifying parameters for the model
- */
- identifyingParams(): Omit & {
- model_name: string;
- } & ClientOptions {
- return this._identifyingParams();
- }
-
- /**
- * Call out to OpenAI's endpoint with k unique prompts
- *
- * @param [prompts] - The prompts to pass into the model.
- * @param [options] - Optional list of stop words to use when generating.
- * @param [runManager] - Optional callback manager to use when generating.
- *
- * @returns The full LLM output.
- *
- * @example
- * ```ts
- * import { OpenAI } from "langchain/llms/openai";
- * const openai = new OpenAI();
- * const response = await openai.generate(["Tell me a joke."]);
- * ```
- */
- async _generate(
- prompts: string[],
- options: this["ParsedCallOptions"],
- runManager?: CallbackManagerForLLMRun
- ): Promise {
- const subPrompts = chunkArray(prompts, this.batchSize);
- const choices: OpenAIClient.CompletionChoice[] = [];
- const tokenUsage: TokenUsage = {};
-
- const params = this.invocationParams(options);
-
- if (params.max_tokens === -1) {
- if (prompts.length !== 1) {
- throw new Error(
- "max_tokens set to -1 not supported for multiple inputs"
- );
- }
- params.max_tokens = await calculateMaxTokens({
- prompt: prompts[0],
- // Cast here to allow for other models that may not fit the union
- modelName: this.modelName as TiktokenModel,
- });
- }
-
- for (let i = 0; i < subPrompts.length; i += 1) {
- const data = params.stream
- ? await (async () => {
- const choices: OpenAIClient.CompletionChoice[] = [];
- let response: Omit | undefined;
- const stream = await this.completionWithRetry(
- {
- ...params,
- stream: true,
- prompt: subPrompts[i],
- },
- options
- );
- for await (const message of stream) {
- // on the first message set the response properties
- if (!response) {
- response = {
- id: message.id,
- object: message.object,
- created: message.created,
- model: message.model,
- };
- }
-
- // on all messages, update choice
- for (const part of message.choices) {
- if (!choices[part.index]) {
- choices[part.index] = part;
- } else {
- const choice = choices[part.index];
- choice.text += part.text;
- choice.finish_reason = part.finish_reason;
- choice.logprobs = part.logprobs;
- }
- void runManager?.handleLLMNewToken(part.text, {
- prompt: Math.floor(part.index / this.n),
- completion: part.index % this.n,
- });
- }
- }
- if (options.signal?.aborted) {
- throw new Error("AbortError");
- }
- return { ...response, choices };
- })()
- : await this.completionWithRetry(
- {
- ...params,
- stream: false,
- prompt: subPrompts[i],
- },
- {
- signal: options.signal,
- ...options.options,
- }
- );
-
- choices.push(...data.choices);
- const {
- completion_tokens: completionTokens,
- prompt_tokens: promptTokens,
- total_tokens: totalTokens,
- } = data.usage
- ? data.usage
- : {
- completion_tokens: undefined,
- prompt_tokens: undefined,
- total_tokens: undefined,
- };
-
- if (completionTokens) {
- tokenUsage.completionTokens =
- (tokenUsage.completionTokens ?? 0) + completionTokens;
- }
-
- if (promptTokens) {
- tokenUsage.promptTokens = (tokenUsage.promptTokens ?? 0) + promptTokens;
- }
-
- if (totalTokens) {
- tokenUsage.totalTokens = (tokenUsage.totalTokens ?? 0) + totalTokens;
- }
- }
-
- const generations = chunkArray(choices, this.n).map((promptChoices) =>
- promptChoices.map((choice) => ({
- text: choice.text ?? "",
- generationInfo: {
- finishReason: choice.finish_reason,
- logprobs: choice.logprobs,
- },
- }))
- );
- return {
- generations,
- llmOutput: { tokenUsage },
- };
- }
-
- // TODO(jacoblee): Refactor with _generate(..., {stream: true}) implementation?
- async *_streamResponseChunks(
- input: string,
- options: this["ParsedCallOptions"],
- runManager?: CallbackManagerForLLMRun
- ): AsyncGenerator {
- const params = {
- ...this.invocationParams(options),
- prompt: input,
- stream: true as const,
- };
- const stream = await this.completionWithRetry(params, options);
- for await (const data of stream) {
- const choice = data?.choices[0];
- if (!choice) {
- continue;
- }
- const chunk = new GenerationChunk({
- text: choice.text,
- generationInfo: {
- finishReason: choice.finish_reason,
- },
- });
- yield chunk;
- // eslint-disable-next-line no-void
- void runManager?.handleLLMNewToken(chunk.text ?? "");
- }
- if (options.signal?.aborted) {
- throw new Error("AbortError");
- }
- }
-
- /**
- * Calls the OpenAI API with retry logic in case of failures.
- * @param request The request to send to the OpenAI API.
- * @param options Optional configuration for the API call.
- * @returns The response from the OpenAI API.
- */
- async completionWithRetry(
- request: OpenAIClient.CompletionCreateParamsStreaming,
- options?: OpenAICoreRequestOptions
- ): Promise>;
-
- async completionWithRetry(
- request: OpenAIClient.CompletionCreateParamsNonStreaming,
- options?: OpenAICoreRequestOptions
- ): Promise;
-
- async completionWithRetry(
- request:
- | OpenAIClient.CompletionCreateParamsStreaming
- | OpenAIClient.CompletionCreateParamsNonStreaming,
- options?: OpenAICoreRequestOptions
- ): Promise<
- AsyncIterable | OpenAIClient.Completions.Completion
- > {
- const requestOptions = this._getClientOptions(options);
- return this.caller.call(async () => {
- try {
- const res = await this.client.completions.create(
- request,
- requestOptions
- );
- return res;
- } catch (e) {
- const error = wrapOpenAIClientError(e);
- throw error;
- }
- });
- }
-
- /**
- * Calls the OpenAI API with retry logic in case of failures.
- * @param request The request to send to the OpenAI API.
- * @param options Optional configuration for the API call.
- * @returns The response from the OpenAI API.
- */
- private _getClientOptions(options: OpenAICoreRequestOptions | undefined) {
- if (!this.client) {
- const openAIEndpointConfig: OpenAIEndpointConfig = {
- azureOpenAIApiDeploymentName: this.azureOpenAIApiDeploymentName,
- azureOpenAIApiInstanceName: this.azureOpenAIApiInstanceName,
- azureOpenAIApiKey: this.azureOpenAIApiKey,
- azureOpenAIBasePath: this.azureOpenAIBasePath,
- baseURL: this.clientConfig.baseURL,
- };
-
- const endpoint = getEndpoint(openAIEndpointConfig);
-
- const params = {
- ...this.clientConfig,
- baseURL: endpoint,
- timeout: this.timeout,
- maxRetries: 0,
- };
-
- if (!params.baseURL) {
- delete params.baseURL;
- }
-
- this.client = new OpenAIClient(params);
- }
- const requestOptions = {
- ...this.clientConfig,
- ...options,
- } as OpenAICoreRequestOptions;
- if (this.azureOpenAIApiKey) {
- requestOptions.headers = {
- "api-key": this.azureOpenAIApiKey,
- ...requestOptions.headers,
- };
- requestOptions.query = {
- "api-version": this.azureOpenAIApiVersion,
- ...requestOptions.query,
- };
- }
- return requestOptions;
- }
-
- _llmType() {
- return "openai";
- }
-}
+export { OpenAI };
/**
* PromptLayer wrapper to OpenAI
diff --git a/langchain/src/llms/portkey.ts b/langchain/src/llms/portkey.ts
index c6a2df313826..79b975e5fabc 100644
--- a/langchain/src/llms/portkey.ts
+++ b/langchain/src/llms/portkey.ts
@@ -1,179 +1 @@
-import _ from "lodash";
-import { LLMOptions, Portkey as _Portkey } from "portkey-ai";
-import { CallbackManagerForLLMRun } from "../callbacks/manager.js";
-import { GenerationChunk, LLMResult } from "../schema/index.js";
-import { getEnvironmentVariable } from "../util/env.js";
-import { BaseLLM } from "./base.js";
-
-interface PortkeyOptions {
- apiKey?: string;
- baseURL?: string;
- mode?: string;
- llms?: [LLMOptions] | null;
-}
-
-const readEnv = (env: string, default_val?: string): string | undefined =>
- getEnvironmentVariable(env) ?? default_val;
-
-export class PortkeySession {
- portkey: _Portkey;
-
- constructor(options: PortkeyOptions = {}) {
- if (!options.apiKey) {
- /* eslint-disable no-param-reassign */
- options.apiKey = readEnv("PORTKEY_API_KEY");
- }
-
- if (!options.baseURL) {
- /* eslint-disable no-param-reassign */
- options.baseURL = readEnv("PORTKEY_BASE_URL", "https://api.portkey.ai");
- }
-
- this.portkey = new _Portkey({});
- this.portkey.llms = [{}];
- if (!options.apiKey) {
- throw new Error("Set Portkey ApiKey in PORTKEY_API_KEY env variable");
- }
-
- this.portkey = new _Portkey(options);
- }
-}
-
-const defaultPortkeySession: {
- session: PortkeySession;
- options: PortkeyOptions;
-}[] = [];
-
-/**
- * Get a session for the Portkey API. If one already exists with the same options,
- * it will be returned. Otherwise, a new session will be created.
- * @param options
- * @returns
- */
-export function getPortkeySession(options: PortkeyOptions = {}) {
- let session = defaultPortkeySession.find((session) =>
- _.isEqual(session.options, options)
- )?.session;
-
- if (!session) {
- session = new PortkeySession(options);
- defaultPortkeySession.push({ session, options });
- }
- return session;
-}
-
-/**
- * @example
- * ```typescript
- * const model = new Portkey({
- * mode: "single",
- * llms: [
- * {
- * provider: "openai",
- * virtual_key: "open-ai-key-1234",
- * model: "text-davinci-003",
- * max_tokens: 2000,
- * },
- * ],
- * });
- *
- * // Stream the output of the model and process it
- * const res = await model.stream(
- * "Question: Write a story about a king\nAnswer:"
- * );
- * for await (const i of res) {
- * process.stdout.write(i);
- * }
- * ```
- */
-export class Portkey extends BaseLLM {
- apiKey?: string = undefined;
-
- baseURL?: string = undefined;
-
- mode?: string = undefined;
-
- llms?: [LLMOptions] | null = undefined;
-
- session: PortkeySession;
-
- constructor(init?: Partial) {
- super(init ?? {});
- this.apiKey = init?.apiKey;
-
- this.baseURL = init?.baseURL;
-
- this.mode = init?.mode;
-
- this.llms = init?.llms;
-
- this.session = getPortkeySession({
- apiKey: this.apiKey,
- baseURL: this.baseURL,
- llms: this.llms,
- mode: this.mode,
- });
- }
-
- _llmType() {
- return "portkey";
- }
-
- async _generate(
- prompts: string[],
- options: this["ParsedCallOptions"],
- _?: CallbackManagerForLLMRun
- ): Promise {
- const choices = [];
- for (let i = 0; i < prompts.length; i += 1) {
- const response = await this.session.portkey.completions.create({
- prompt: prompts[i],
- ...options,
- stream: false,
- });
- choices.push(response.choices);
- }
- const generations = choices.map((promptChoices) =>
- promptChoices.map((choice) => ({
- text: choice.text ?? "",
- generationInfo: {
- finishReason: choice.finish_reason,
- logprobs: choice.logprobs,
- },
- }))
- );
-
- return {
- generations,
- };
- }
-
- async *_streamResponseChunks(
- input: string,
- options: this["ParsedCallOptions"],
- runManager?: CallbackManagerForLLMRun
- ): AsyncGenerator {
- const response = await this.session.portkey.completions.create({
- prompt: input,
- ...options,
- stream: true,
- });
- for await (const data of response) {
- const choice = data?.choices[0];
- if (!choice) {
- continue;
- }
- const chunk = new GenerationChunk({
- text: choice.text ?? "",
- generationInfo: {
- finishReason: choice.finish_reason,
- },
- });
- yield chunk;
- void runManager?.handleLLMNewToken(chunk.text ?? "");
- }
- if (options.signal?.aborted) {
- throw new Error("AbortError");
- }
- }
-}
+export * from "@langchain/community/llms/portkey";
diff --git a/langchain/src/llms/raycast.ts b/langchain/src/llms/raycast.ts
index 7901f0fde238..a36430dc3817 100644
--- a/langchain/src/llms/raycast.ts
+++ b/langchain/src/llms/raycast.ts
@@ -1,99 +1 @@
-import { AI, environment } from "@raycast/api";
-import { LLM, BaseLLMParams } from "./base.js";
-
-/**
- * The input parameters for the RaycastAI class, which extends the BaseLLMParams interface.
- */
-export interface RaycastAIInput extends BaseLLMParams {
- model?: AI.Model;
- creativity?: number;
- rateLimitPerMinute?: number;
-}
-
-const wait = (ms: number) =>
- new Promise((resolve) => {
- setTimeout(resolve, ms);
- });
-
-/**
- * The RaycastAI class, which extends the LLM class and implements the RaycastAIInput interface.
- */
-export class RaycastAI extends LLM implements RaycastAIInput {
- /**
- * The model to use for generating text.
- */
- model: AI.Model;
-
- /**
- * The creativity parameter, also known as the "temperature".
- */
- creativity: number;
-
- /**
- * The rate limit for API calls, in requests per minute.
- */
- rateLimitPerMinute: number;
-
- /**
- * The timestamp of the last API call, used to enforce the rate limit.
- */
- private lastCallTimestamp = 0;
-
- /**
- * Creates a new instance of the RaycastAI class.
- * @param {RaycastAIInput} fields The input parameters for the RaycastAI class.
- * @throws {Error} If the Raycast AI environment is not accessible.
- */
- constructor(fields: RaycastAIInput) {
- super(fields ?? {});
-
- if (!environment.canAccess(AI)) {
- throw new Error("Raycast AI environment is not accessible.");
- }
-
- this.model = fields.model ?? "text-davinci-003";
- this.creativity = fields.creativity ?? 0.5;
- this.rateLimitPerMinute = fields.rateLimitPerMinute ?? 10;
- }
-
- /**
- * Returns the type of the LLM, which is "raycast_ai".
- * @return {string} The type of the LLM.
- * @ignore
- */
- _llmType() {
- return "raycast_ai";
- }
-
- /**
- * Calls AI.ask with the given prompt and returns the generated text.
- * @param {string} prompt The prompt to generate text from.
- * @return {Promise} A Promise that resolves to the generated text.
- * @ignore
- */
- async _call(
- prompt: string,
- options: this["ParsedCallOptions"]
- ): Promise {
- const response = await this.caller.call(async () => {
- // Rate limit calls to Raycast AI
- const now = Date.now();
- const timeSinceLastCall = now - this.lastCallTimestamp;
- const timeToWait =
- (60 / this.rateLimitPerMinute) * 1000 - timeSinceLastCall;
-
- if (timeToWait > 0) {
- await wait(timeToWait);
- }
-
- return await AI.ask(prompt, {
- model: this.model,
- creativity: this.creativity,
- signal: options.signal,
- });
- });
-
- // Since Raycast AI returns the response directly, no need for output transformation
- return response;
- }
-}
+export * from "@langchain/community/llms/raycast";
diff --git a/langchain/src/llms/replicate.ts b/langchain/src/llms/replicate.ts
index 27fa66c5eb7c..72c1ca24a637 100644
--- a/langchain/src/llms/replicate.ts
+++ b/langchain/src/llms/replicate.ts
@@ -1,158 +1 @@
-import { getEnvironmentVariable } from "../util/env.js";
-import { LLM, BaseLLMParams } from "./base.js";
-
-/**
- * Interface defining the structure of the input data for the Replicate
- * class. It includes details about the model to be used, any additional
- * input parameters, and the API key for the Replicate service.
- */
-export interface ReplicateInput {
- // owner/model_name:version
- model: `${string}/${string}:${string}`;
-
- input?: {
- // different models accept different inputs
- [key: string]: string | number | boolean;
- };
-
- apiKey?: string;
-
- /** The key used to pass prompts to the model. */
- promptKey?: string;
-}
-
-/**
- * Class responsible for managing the interaction with the Replicate API.
- * It handles the API key and model details, makes the actual API calls,
- * and converts the API response into a format usable by the rest of the
- * LangChain framework.
- * @example
- * ```typescript
- * const model = new Replicate({
- * model: "replicate/flan-t5-xl:3ae0799123a1fe11f8c89fd99632f843fc5f7a761630160521c4253149754523",
- * });
- *
- * const res = await model.call(
- * "Question: What would be a good company name for a company that makes colorful socks?\nAnswer:"
- * );
- * console.log({ res });
- * ```
- */
-export class Replicate extends LLM implements ReplicateInput {
- static lc_name() {
- return "Replicate";
- }
-
- get lc_secrets(): { [key: string]: string } | undefined {
- return {
- apiKey: "REPLICATE_API_TOKEN",
- };
- }
-
- lc_serializable = true;
-
- model: ReplicateInput["model"];
-
- input: ReplicateInput["input"];
-
- apiKey: string;
-
- promptKey?: string;
-
- constructor(fields: ReplicateInput & BaseLLMParams) {
- super(fields);
-
- const apiKey =
- fields?.apiKey ??
- getEnvironmentVariable("REPLICATE_API_KEY") ?? // previous environment variable for backwards compatibility
- getEnvironmentVariable("REPLICATE_API_TOKEN"); // current environment variable, matching the Python library
-
- if (!apiKey) {
- throw new Error(
- "Please set the REPLICATE_API_TOKEN environment variable"
- );
- }
-
- this.apiKey = apiKey;
- this.model = fields.model;
- this.input = fields.input ?? {};
- this.promptKey = fields.promptKey;
- }
-
- _llmType() {
- return "replicate";
- }
-
- /** @ignore */
- async _call(
- prompt: string,
- options: this["ParsedCallOptions"]
- ): Promise {
- const imports = await Replicate.imports();
-
- const replicate = new imports.Replicate({
- userAgent: "langchain",
- auth: this.apiKey,
- });
-
- if (this.promptKey === undefined) {
- const [modelString, versionString] = this.model.split(":");
- const version = await replicate.models.versions.get(
- modelString.split("/")[0],
- modelString.split("/")[1],
- versionString
- );
- const openapiSchema = version.openapi_schema;
- const inputProperties: { "x-order": number | undefined }[] =
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- (openapiSchema as any)?.components?.schemas?.Input?.properties;
- if (inputProperties === undefined) {
- this.promptKey = "prompt";
- } else {
- const sortedInputProperties = Object.entries(inputProperties).sort(
- ([_keyA, valueA], [_keyB, valueB]) => {
- const orderA = valueA["x-order"] || 0;
- const orderB = valueB["x-order"] || 0;
- return orderA - orderB;
- }
- );
- this.promptKey = sortedInputProperties[0][0] ?? "prompt";
- }
- }
- const output = await this.caller.callWithOptions(
- { signal: options.signal },
- () =>
- replicate.run(this.model, {
- input: {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- [this.promptKey!]: prompt,
- ...this.input,
- },
- })
- );
-
- if (typeof output === "string") {
- return output;
- } else if (Array.isArray(output)) {
- return output.join("");
- } else {
- // Note this is a little odd, but the output format is not consistent
- // across models, so it makes some amount of sense.
- return String(output);
- }
- }
-
- /** @ignore */
- static async imports(): Promise<{
- Replicate: typeof import("replicate").default;
- }> {
- try {
- const { default: Replicate } = await import("replicate");
- return { Replicate };
- } catch (e) {
- throw new Error(
- "Please install replicate as a dependency with, e.g. `yarn add replicate`"
- );
- }
- }
-}
+export * from "@langchain/community/llms/replicate";
diff --git a/langchain/src/llms/sagemaker_endpoint.ts b/langchain/src/llms/sagemaker_endpoint.ts
index 38706d608417..f9a5e590c0fb 100644
--- a/langchain/src/llms/sagemaker_endpoint.ts
+++ b/langchain/src/llms/sagemaker_endpoint.ts
@@ -1,283 +1 @@
-import {
- InvokeEndpointCommand,
- InvokeEndpointWithResponseStreamCommand,
- SageMakerRuntimeClient,
- SageMakerRuntimeClientConfig,
-} from "@aws-sdk/client-sagemaker-runtime";
-import { CallbackManagerForLLMRun } from "../callbacks/manager.js";
-import { GenerationChunk } from "../schema/index.js";
-import { BaseLLMCallOptions, BaseLLMParams, LLM } from "./base.js";
-
-/**
- * A handler class to transform input from LLM to a format that SageMaker
- * endpoint expects. Similarily, the class also handles transforming output from
- * the SageMaker endpoint to a format that LLM class expects.
- *
- * Example:
- * ```
- * class ContentHandler implements ContentHandlerBase