Make openai classes use fetch, remove use of node-fetch (#118), Convert library to ESM codebase, ESM output (#124), Add GH (manual) action for running integration tests (#119)

* Use fetch adapter for openai axios

* Remove node-fetch, add instructions for node 16

* Add GH (manual) action for running integration tests (#119)

* Add integration tests GH action (manual trigger for now), reduce cost of integration tests by using smallest possible models

* Convert library to ESM codebase, ESM output (#124)

* Use fetch adapter for openai axios

* Update tsc build to output ESM only

* Update all import paths to have extension per ESM requirements

* Move all source files to src/

* Remove circular dependency

* Fix jest config for ESM

* Remove circular deps not possible with ESM

* Throw error in index getter to dedupe code and have safer usage (#35)

* Fix hnsw for esm

* Fix usage of hnswlib with index passed in

* Fix textsplitter for esm

* Fix openai for esm

* Fix hf for esm

* Fix ESM for cohere

* Fix ESM for serpapi

* Fix esm in srt

* Remove dependency on @vespaiach/axios-fetch-adapter which has an incorrect export

* Fix examples for esm

* Fix entrypoints

* Fix test-exports for esm

* Add fetch flag for node 16 ci job

* Add a more thorough test for packaging

* Fix docs build

---------

Co-authored-by: micahriggan <micahriggan@users.noreply.github.com>

---------

Co-authored-by: micahriggan <micahriggan@users.noreply.github.com>

* Fix one more import

* Fix example

* Also build docs in ci

* Fix sql test in ci

---------

Co-authored-by: micahriggan <micahriggan@users.noreply.github.com>
This commit is contained in:
Nuno Campos
2023-02-27 13:57:22 +00:00
committed by GitHub
parent fced19c59c
commit 1f7045a71f
145 changed files with 1255 additions and 770 deletions
+3
View File
@@ -29,3 +29,6 @@ jobs:
run: yarn install --immutable
- run: yarn run ci
- run: yarn workspace langchain run test
if: matrix.node-version != '16.x'
- run: yarn workspace langchain run test:node16
if: matrix.node-version == '16.x'
+29
View File
@@ -0,0 +1,29 @@
# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs
name: Node.js Integration Tests
on:
workflow_dispatch:
jobs:
build:
strategy:
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
node-version: [16.x, 18.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: "yarn"
- name: Install dependencies
run: yarn install --immutable
- run: yarn run ci
- run: yarn workspace langchain run test:integration
+5
View File
@@ -10,6 +10,11 @@ To get started, install LangChain with the following command:
npm i langchain
```
If you are running this on Node.js 16, either:
- run your application with `NODE_OPTIONS='--experimental-fetch' node ...`, or
- install `node-fetch` and follow the instructions [here](https://github.com/node-fetch/node-fetch#providing-global-access)
## Picking up a LLM
Using LangChain will usually require integrations with one or more model providers, data stores, apis, etc.
+1 -1
View File
@@ -12,7 +12,7 @@
"serve": "docusaurus serve",
"write-translations": "docusaurus write-translations",
"write-heading-ids": "docusaurus write-heading-ids",
"ci": "yarn lint && yarn format:diff",
"ci": "yarn lint && yarn format:diff && yarn build",
"lint": "eslint --cache \"**/*.js\"",
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,md,mdx}\"",
"format:diff": "prettier --list-different \"**/*.{js,jsx,ts,tsx,md,mdx}\""
+1
View File
@@ -4,6 +4,7 @@
"private": true,
"description": "Langchain examples",
"main": "./dist/index.js",
"type": "module",
"files": [
"dist/"
],
+1 -1
View File
@@ -13,7 +13,7 @@ export const run = async () => {
const text = fs.readFileSync("state_of_the_union.txt", "utf8");
/* Split the text into chunks */
const textSplitter = new RecursiveCharacterTextSplitter({ chunkSize: 1000 });
const docs = textSplitter.createDocuments([text]);
const docs = await textSplitter.createDocuments([text]);
/* Create the vectorstore */
const vectorStore = await HNSWLib.fromDocuments(docs, new OpenAIEmbeddings());
/* Create the chain */
+1 -1
View File
@@ -12,7 +12,7 @@ export const run = async () => {
const text = fs.readFileSync("state_of_the_union.txt", "utf8");
/* Split the text into chunks */
const textSplitter = new RecursiveCharacterTextSplitter({ chunkSize: 1000 });
const docs = textSplitter.createDocuments([text]);
const docs = await textSplitter.createDocuments([text]);
/* Create the vectorstore */
const vectorStore = await HNSWLib.fromDocuments(docs, new OpenAIEmbeddings());
/* Create the chain */
+1 -1
View File
@@ -14,7 +14,7 @@ export const run = async () => {
const text = fs.readFileSync("state_of_the_union.txt", "utf8");
/* Split the text into chunks */
const textSplitter = new RecursiveCharacterTextSplitter({ chunkSize: 1000 });
const docs = textSplitter.createDocuments([text]);
const docs = await textSplitter.createDocuments([text]);
/* Create the vectorstore */
const vectorStore = await Chroma.fromDocuments(
docs,
+1 -1
View File
@@ -12,7 +12,7 @@ export const run = async () => {
const text = fs.readFileSync("state_of_the_union.txt", "utf8");
/* Split the text into chunks */
const textSplitter = new RecursiveCharacterTextSplitter({ chunkSize: 1000 });
const docs = textSplitter.createDocuments([text]);
const docs = await textSplitter.createDocuments([text]);
/* Create the vectorstore */
const vectorStore = await HNSWLib.fromDocuments(docs, new OpenAIEmbeddings());
/* Create the chain */
+1
View File
@@ -4,6 +4,7 @@
"outDir": "dist",
"lib": [
"ESNext",
"DOM"
],
"sourceMap": true,
"allowSyntheticDefaultImports": true,
@@ -12,7 +12,7 @@ module.exports = {
sourceType: "module",
},
plugins: ["@typescript-eslint"],
ignorePatterns: ["dist", "docs", "node_modules", "*.d.ts", "*.js", "*.mjs"],
ignorePatterns: ["dist", "docs", "node_modules", "*.d.ts", "*.cjs", "*.js"],
rules: {
"@typescript-eslint/explicit-module-boundary-types": 0,
"@typescript-eslint/no-empty-function": 0,
-13
View File
@@ -1,39 +1,26 @@
agents.js
agents.mjs
agents.d.ts
tools.js
tools.mjs
tools.d.ts
chains.js
chains.mjs
chains.d.ts
embeddings.js
embeddings.mjs
embeddings.d.ts
llms.js
llms.mjs
llms.d.ts
prompts.js
prompts.mjs
prompts.d.ts
vectorstores.js
vectorstores.mjs
vectorstores.d.ts
text_splitter.js
text_splitter.mjs
text_splitter.d.ts
memory.js
memory.mjs
memory.d.ts
document.js
document.mjs
document.d.ts
docstore.js
docstore.mjs
docstore.d.ts
document_loaders.js
document_loaders.mjs
document_loaders.d.ts
index.js
index.mjs
index.d.ts
-5
View File
@@ -1,5 +0,0 @@
dist/
docs/
*.js
*.mjs
*.d.ts
-3
View File
@@ -1,3 +0,0 @@
export { JsonToolkit, createJsonAgent } from "./json";
export { SqlToolkit, createSqlAgent } from "./sql";
export { RequestsToolkit, OpenApiToolkit, createOpenApiAgent } from "./openapi";
-23
View File
@@ -1,23 +0,0 @@
export {
AgentAction,
AgentFinish,
AgentStep,
StoppingMethod,
SerializedAgentT,
} from "./types";
export { Agent, StaticAgent, staticImplements, AgentInput } from "./agent";
export { AgentExecutor } from "./executor";
export { ZeroShotAgent, SerializedZeroShotAgent } from "./mrkl";
export { Tool } from "./tools";
export { initializeAgentExecutor } from "./initialize";
export { loadAgent } from "./load";
export {
SqlToolkit,
JsonToolkit,
RequestsToolkit,
OpenApiToolkit,
createSqlAgent,
createJsonAgent,
createOpenApiAgent,
} from "./agent_toolkits";
-23
View File
@@ -1,23 +0,0 @@
export { SerpAPI } from "./serpapi";
export { Calculator } from "./calculator";
export { DadJokeAPI } from "./dadjokeapi";
export { BingSerpAPI } from "./bingserpapi";
export { Tool } from "./base";
export { DynamicTool } from "./dynamic";
export { IFTTTWebhook } from "./IFTTTWebhook";
export { ChainTool } from "./chain";
export {
SqlDatabase,
QuerySqlTool,
InfoSqlTool,
ListTablesSqlTool,
QueryCheckerTool,
} from "./sql";
export {
JsonSpec,
JsonListKeysTool,
JsonGetValueTool,
JsonObject,
Json,
} from "./json";
export { RequestsGetTool, RequestsPostTool } from "./requests";
+12 -12
View File
@@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const path = require("path");
const fs = require("fs");
import path from "path";
import url from "url";
import fs from "fs";
const entrypoints = {
agents: "agents/index",
@@ -18,7 +18,10 @@ const entrypoints = {
};
const updateJsonFile = (relativePath, updateFunction) => {
const filePath = path.resolve(__dirname, relativePath);
const filePath = path.resolve(
path.dirname(url.fileURLToPath(import.meta.url)),
relativePath
);
const contents = fs.readFileSync(filePath).toString();
const res = updateFunction(JSON.parse(contents));
fs.writeFileSync(filePath, JSON.stringify(res, null, 2));
@@ -27,12 +30,9 @@ const updateJsonFile = (relativePath, updateFunction) => {
const generateFiles = () => {
const files = [...Object.entries(entrypoints), ["index", "index"]].flatMap(
([key, value]) => {
const modulePath =
path.basename(value) === "index" ? path.dirname(value) : value;
const compiledPath = `./dist/${modulePath}`;
const compiledPath = `./dist/${value}.js`;
return [
[`${key}.js`, `module.exports = require('${compiledPath}')`],
[`${key}.mjs`, `export * from './dist/${value}.js'`],
[`${key}.js`, `export * from '${compiledPath}'`],
[`${key}.d.ts`, `export * from '${compiledPath}'`],
];
}
@@ -47,7 +47,7 @@ const updateConfig = () => {
typedocOptions: {
...json.typedocOptions,
entryPoints: [...Object.values(entrypoints), "index"].map(
(value) => `./${value}.ts`
(value) => `src/${value}.ts`
),
},
}));
@@ -60,8 +60,8 @@ const updateConfig = () => {
exports: Object.fromEntries(
["index", ...Object.keys(entrypoints)].map((key) => {
const entryPoint = {
import: `./${key}.mjs`,
default: `./${key}.js`,
types: `./${key}.d.ts`,
import: `./${key}.js`,
};
return [key === "index" ? "." : `./${key}`, entryPoint];
})
-3
View File
@@ -1,3 +0,0 @@
export { Document } from "../document";
export { Docstore } from "./base";
export { InMemoryDocstore } from "./in_memory";
-9
View File
@@ -1,9 +0,0 @@
export type { DocumentLoader } from "./base";
export { BaseDocumentLoader } from "./base";
export { CheerioWebBaseLoader } from "./cheerio_web_base";
export { CollegeConfidentialLoader } from "./college_confidential";
export { GitbookLoader } from "./gitbook";
export { HNLoader } from "./hn";
export { IMSDBLoader } from "./imsdb";
export { SRTLoader } from "./srt";
export { TextLoader } from "./text";
-1
View File
@@ -1 +0,0 @@
export { OpenAIEmbeddings } from "./openai";
-8
View File
@@ -1,8 +0,0 @@
export {
PromptTemplate,
BasePromptTemplate,
FewShotPromptTemplate,
} from "./prompts";
export { LLMChain } from "./chains";
export { OpenAI } from "./llms";
@@ -1,12 +1,13 @@
/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
preset: "ts-jest/presets/js-with-ts",
preset: "ts-jest/presets/default-esm",
testEnvironment: "node",
modulePathIgnorePatterns: ["dist/", "docs/"],
transform: {
"^.+\\.(ts|tsx)$": "ts-jest",
"^.+\\.(js)$": "babel-jest",
moduleNameMapper: {
"^(\\.{1,2}/.*)\\.js$": "$1",
},
transform: {
"^.+\\.m?[tj]sx?$": ["ts-jest", { useESM: true }],
},
transformIgnorePatterns: [],
setupFiles: ["dotenv/config"],
};
-3
View File
@@ -1,3 +0,0 @@
export { BufferMemory } from "./buffer_memory";
export { BaseMemory } from "./base";
export { BufferWindowMemory } from "./buffer_window_memory";
+34 -46
View File
@@ -2,48 +2,36 @@
"name": "langchain",
"version": "0.0.12",
"description": "Typescript bindings for langchain",
"type": "module",
"main": "./index.js",
"types": "./index.d.ts",
"files": [
"dist/",
"agents.js",
"agents.mjs",
"agents.d.ts",
"tools.js",
"tools.mjs",
"tools.d.ts",
"chains.js",
"chains.mjs",
"chains.d.ts",
"embeddings.js",
"embeddings.mjs",
"embeddings.d.ts",
"llms.js",
"llms.mjs",
"llms.d.ts",
"prompts.js",
"prompts.mjs",
"prompts.d.ts",
"vectorstores.js",
"vectorstores.mjs",
"vectorstores.d.ts",
"text_splitter.js",
"text_splitter.mjs",
"text_splitter.d.ts",
"memory.js",
"memory.mjs",
"memory.d.ts",
"document.js",
"document.mjs",
"document.d.ts",
"docstore.js",
"docstore.mjs",
"docstore.d.ts",
"document_loaders.js",
"document_loaders.mjs",
"document_loaders.d.ts",
"index.js",
"index.mjs",
"index.d.ts"
],
"repository": {
@@ -58,11 +46,12 @@
"precommit": "tsc --noEmit && lint-staged",
"clean": "rm -rf dist/ && node create-entrypoints.js clean",
"prepack": "yarn build",
"test": "yarn clean && jest --testPathIgnorePatterns=\\.int\\.test.ts",
"test:integration": "yarn clean && jest --testPathPattern=\\.int\\.test.ts --testTimeout 20000",
"test": "yarn clean && NODE_OPTIONS=--experimental-vm-modules jest --testPathIgnorePatterns=\\.int\\.test.ts",
"test:node16": "yarn clean && NODE_OPTIONS='--experimental-vm-modules --experimental-fetch' jest --testPathIgnorePatterns=\\.int\\.test.ts",
"test:integration": "yarn clean && NODE_OPTIONS=--experimental-vm-modules jest --testPathPattern=\\.int\\.test.ts --testTimeout 20000",
"prepare": "husky install",
"format": "prettier --write \"**/*.ts\"",
"format:diff": "prettier --list-different \"**/*.ts\"",
"format": "prettier --write \"src\"",
"format:diff": "prettier --list-different \"src\"",
"ci": "yarn lint && yarn format:diff && yarn build"
},
"author": "Langchain",
@@ -74,7 +63,6 @@
"@jest/globals": "^29.4.2",
"@pinecone-database/pinecone": "^0.0.8",
"@tsconfig/recommended": "^1.0.2",
"@types/node-fetch": "2",
"@types/uuid": "^9",
"@typescript-eslint/eslint-plugin": "^5.51.0",
"@typescript-eslint/parser": "^5.51.0",
@@ -144,14 +132,14 @@
}
},
"dependencies": {
"browser-or-node": "^2.1.1",
"deepcopy": "^2.1.0",
"eventsource-parser": "^0.1.0",
"exponential-backoff": "^3.1.0",
"expr-eval": "^2.0.2",
"gpt-3-encoder": "^1.1.4",
"jsonpointer": "^5.0.1",
"node-fetch": "2",
"p-queue": "6",
"p-queue": "^7.3.4",
"sqlite3": "^5.1.4",
"uuid": "^9.0.0",
"yaml": "^2.2.1"
@@ -181,56 +169,56 @@
],
"exports": {
".": {
"import": "./index.mjs",
"default": "./index.js"
"types": "./index.d.ts",
"import": "./index.js"
},
"./agents": {
"import": "./agents.mjs",
"default": "./agents.js"
"types": "./agents.d.ts",
"import": "./agents.js"
},
"./tools": {
"import": "./tools.mjs",
"default": "./tools.js"
"types": "./tools.d.ts",
"import": "./tools.js"
},
"./chains": {
"import": "./chains.mjs",
"default": "./chains.js"
"types": "./chains.d.ts",
"import": "./chains.js"
},
"./embeddings": {
"import": "./embeddings.mjs",
"default": "./embeddings.js"
"types": "./embeddings.d.ts",
"import": "./embeddings.js"
},
"./llms": {
"import": "./llms.mjs",
"default": "./llms.js"
"types": "./llms.d.ts",
"import": "./llms.js"
},
"./prompts": {
"import": "./prompts.mjs",
"default": "./prompts.js"
"types": "./prompts.d.ts",
"import": "./prompts.js"
},
"./vectorstores": {
"import": "./vectorstores.mjs",
"default": "./vectorstores.js"
"types": "./vectorstores.d.ts",
"import": "./vectorstores.js"
},
"./text_splitter": {
"import": "./text_splitter.mjs",
"default": "./text_splitter.js"
"types": "./text_splitter.d.ts",
"import": "./text_splitter.js"
},
"./memory": {
"import": "./memory.mjs",
"default": "./memory.js"
"types": "./memory.d.ts",
"import": "./memory.js"
},
"./document": {
"import": "./document.mjs",
"default": "./document.js"
"types": "./document.d.ts",
"import": "./document.js"
},
"./docstore": {
"import": "./docstore.mjs",
"default": "./docstore.js"
"types": "./docstore.d.ts",
"import": "./docstore.js"
},
"./document_loaders": {
"import": "./document_loaders.mjs",
"default": "./document_loaders.js"
"types": "./document_loaders.d.ts",
"import": "./document_loaders.js"
}
}
}
@@ -1,4 +1,4 @@
import { ChainValues } from "../chains";
import { ChainValues } from "../chains/index.js";
import {
ZeroShotAgent,
SerializedZeroShotAgent,
@@ -7,10 +7,10 @@ import {
AgentStep,
StoppingMethod,
Tool,
} from "./index";
import { BaseLLM } from "../llms";
import { LLMChain } from "../chains/llm_chain";
import { BasePromptTemplate } from "../prompts";
} from "./index.js";
import { BaseLLM } from "../llms/index.js";
import { LLMChain } from "../chains/llm_chain.js";
import { BasePromptTemplate } from "../prompts/index.js";
class ParseError extends Error {
output: string;
@@ -1,4 +1,4 @@
import { Tool } from "../tools";
import { Tool } from "../tools/base.js";
export abstract class Toolkit {
abstract tools: Tool[];
@@ -0,0 +1,7 @@
export { JsonToolkit, createJsonAgent } from "./json.js";
export { SqlToolkit, createSqlAgent } from "./sql.js";
export {
RequestsToolkit,
OpenApiToolkit,
createOpenApiAgent,
} from "./openapi.js";
@@ -1,10 +1,15 @@
import { BaseLLM } from "../../llms";
import { JsonGetValueTool, JsonListKeysTool, JsonSpec, Tool } from "../tools";
import { JSON_PREFIX, JSON_SUFFIX } from "./prompt";
import { LLMChain } from "../../chains";
import { CreatePromptArgs, ZeroShotAgent } from "../mrkl";
import { Toolkit } from "./base";
import { AgentExecutor } from "../executor";
import { BaseLLM } from "../../llms/index.js";
import {
JsonGetValueTool,
JsonListKeysTool,
JsonSpec,
Tool,
} from "../tools/index.js";
import { JSON_PREFIX, JSON_SUFFIX } from "./prompt.js";
import { LLMChain } from "../../chains/index.js";
import { CreatePromptArgs, ZeroShotAgent } from "../mrkl/index.js";
import { Toolkit } from "./base.js";
import { AgentExecutor } from "../executor.js";
export class JsonToolkit extends Toolkit {
tools: Tool[];
@@ -1,22 +1,22 @@
import { BaseLLM } from "../../llms";
import { BaseLLM } from "../../llms/index.js";
import {
DynamicTool,
JsonSpec,
RequestsGetTool,
RequestsPostTool,
Tool,
} from "../tools";
import { AgentExecutor } from "../executor";
} from "../tools/index.js";
import { AgentExecutor } from "../executor.js";
import {
OPENAPI_PREFIX,
OPENAPI_SUFFIX,
JSON_EXPLORER_DESCRIPTION,
} from "./prompt";
import { LLMChain } from "../../chains";
import { CreatePromptArgs, ZeroShotAgent } from "../mrkl";
import { Toolkit } from "./base";
import { Headers } from "../tools/requests";
import { createJsonAgent, JsonToolkit } from "./json";
} from "./prompt.js";
import { LLMChain } from "../../chains/index.js";
import { CreatePromptArgs, ZeroShotAgent } from "../mrkl/index.js";
import { Toolkit } from "./base.js";
import { Headers } from "../tools/requests.js";
import { createJsonAgent, JsonToolkit } from "./json.js";
export class RequestsToolkit extends Toolkit {
tools: Tool[];
@@ -5,14 +5,14 @@ import {
QueryCheckerTool,
QuerySqlTool,
SqlDatabase,
} from "../tools";
import { Toolkit } from "./base";
import { BaseLLM } from "../../llms";
import { SQL_PREFIX, SQL_SUFFIX } from "./prompt";
import { interpolateFString } from "../../prompts/template";
import { LLMChain } from "../../chains";
import { ZeroShotAgent, CreatePromptArgs } from "../mrkl";
import { AgentExecutor } from "../executor";
} from "../tools/index.js";
import { Toolkit } from "./base.js";
import { BaseLLM } from "../../llms/index.js";
import { SQL_PREFIX, SQL_SUFFIX } from "./prompt.js";
import { interpolateFString } from "../../prompts/template.js";
import { LLMChain } from "../../chains/index.js";
import { ZeroShotAgent, CreatePromptArgs } from "../mrkl/index.js";
import { AgentExecutor } from "../executor.js";
type SqlCreatePromptArgs = {
/** Number of results to return. */
@@ -1,6 +1,12 @@
import { ChainValues, BaseChain } from "../chains";
import { Agent, Tool, StoppingMethod, AgentStep, AgentFinish } from "./index";
import { SerializedLLMChain } from "../chains/llm_chain";
import { ChainValues, BaseChain } from "../chains/index.js";
import {
Agent,
Tool,
StoppingMethod,
AgentStep,
AgentFinish,
} from "./index.js";
import { SerializedLLMChain } from "../chains/llm_chain.js";
type AgentExecutorInput = {
agent: Agent;
@@ -1,7 +1,8 @@
import { SerializedAgentT, Tool, AgentInput } from "./index";
import { BaseLLM } from "../llms";
import { SerializedLLMChain, LLMChain } from "../chains";
import { resolveConfigFromFile } from "../util";
import type { SerializedAgentT, AgentInput } from "./index.js";
import { Tool } from "./tools/index.js";
import { BaseLLM } from "../llms/index.js";
import { SerializedLLMChain, LLMChain } from "../chains/index.js";
import { resolveConfigFromFile } from "../util/index.js";
export const deserializeHelper = async <
T extends string,
+24
View File
@@ -0,0 +1,24 @@
export {
AgentAction,
AgentFinish,
AgentStep,
StoppingMethod,
SerializedAgentT,
} from "./types.js";
export { Agent, StaticAgent, staticImplements, AgentInput } from "./agent.js";
export { AgentExecutor } from "./executor.js";
export { ZeroShotAgent, SerializedZeroShotAgent } from "./mrkl/index.js";
export { Tool } from "./tools/index.js";
export { initializeAgentExecutor } from "./initialize.js";
export { loadAgent } from "./load.js";
export {
SqlToolkit,
JsonToolkit,
RequestsToolkit,
OpenApiToolkit,
createSqlAgent,
createJsonAgent,
createOpenApiAgent,
} from "./agent_toolkits/index.js";
@@ -1,7 +1,7 @@
import { Tool } from "./tools";
import { BaseLLM } from "../llms";
import { AgentExecutor } from "./executor";
import { ZeroShotAgent } from "./mrkl";
import { Tool } from "./tools/index.js";
import { BaseLLM } from "../llms/index.js";
import { AgentExecutor } from "./executor.js";
import { ZeroShotAgent } from "./mrkl/index.js";
export const initializeAgentExecutor = async (
tools: Tool[],
@@ -1,7 +1,7 @@
import { Agent, Tool } from ".";
import { BaseLLM } from "../llms";
import { loadFromHub } from "../util/hub";
import { FileLoader, loadFromFile, parseFileConfig } from "../util";
import { Agent, Tool } from "./index.js";
import { BaseLLM } from "../llms/index.js";
import { loadFromHub } from "../util/hub.js";
import { FileLoader, loadFromFile, parseFileConfig } from "../util/index.js";
const loadAgentFromFile: FileLoader<Agent> = async (
file: string,
@@ -1,5 +1,5 @@
import { BaseLLM } from "../../llms";
import { LLMChain } from "../../chains";
import { BaseLLM } from "../../llms/index.js";
import { LLMChain } from "../../chains/index.js";
import {
Agent,
Tool,
@@ -7,10 +7,10 @@ import {
StaticAgent,
staticImplements,
SerializedAgentT,
} from "../index";
import { PromptTemplate } from "../../prompts";
import { PREFIX, SUFFIX, formatInstructions } from "./prompt";
import { deserializeHelper } from "../helpers";
} from "../index.js";
import { PromptTemplate } from "../../prompts/index.js";
import { PREFIX, SUFFIX, formatInstructions } from "./prompt.js";
import { deserializeHelper } from "../helpers.js";
const FINAL_ANSWER_ACTION = "Final Answer:";
@@ -1,13 +1,13 @@
import { test } from "@jest/globals";
import { OpenAI } from "../../llms/openai";
import { loadAgent } from "../load";
import { AgentExecutor, Tool } from "../index";
import { SerpAPI } from "../tools/serpapi";
import { Calculator } from "../tools/calculator";
import { initializeAgentExecutor } from "../initialize";
import { OpenAI } from "../../llms/openai.js";
import { loadAgent } from "../load.js";
import { AgentExecutor, Tool } from "../index.js";
import { SerpAPI } from "../tools/serpapi.js";
import { Calculator } from "../tools/calculator.js";
import { initializeAgentExecutor } from "../initialize.js";
test("Run agent from hub", async () => {
const model = new OpenAI({ temperature: 0 });
const model = new OpenAI({ temperature: 0, modelName: "text-babbage-001" });
const tools: Tool[] = [new SerpAPI(), new Calculator()];
const agent = await loadAgent(
"lc://agents/zero-shot-react-description/agent.json",
@@ -26,7 +26,7 @@ test("Run agent from hub", async () => {
}, 30000);
test("Run agent locally", async () => {
const model = new OpenAI({ temperature: 0 });
const model = new OpenAI({ temperature: 0, modelName: "text-babbage-001" });
const tools = [new SerpAPI(), new Calculator()];
const executor = await initializeAgentExecutor(
@@ -1,5 +1,5 @@
import { test, expect } from "@jest/globals";
import { Calculator } from "../tools/calculator";
import { Calculator } from "../tools/calculator.js";
test("Calculator tool, sum", async () => {
const calculator = new Calculator();
@@ -1,5 +1,5 @@
import { test, expect } from "@jest/globals";
import { JsonListKeysTool, JsonSpec, JsonGetValueTool } from "../tools/json";
import { JsonListKeysTool, JsonSpec, JsonGetValueTool } from "../tools/json.js";
test("JsonListKeysTool", async () => {
const jsonSpec = new JsonSpec({
@@ -6,10 +6,12 @@ import {
SqlDatabase,
ListTablesSqlTool,
QueryCheckerTool,
} from "../tools/sql";
} from "../tools/sql.js";
let db: sqlite3.Database;
const previousEnv = process.env;
beforeEach(() => {
db = new sqlite3.Database(":memory:");
db.serialize(() => {
@@ -27,10 +29,14 @@ beforeEach(() => {
db.run("INSERT INTO products (name, price) VALUES ('Banana', 200)");
db.run("INSERT INTO products (name, price) VALUES ('Orange', 300)");
});
process.env = { ...previousEnv, OPENAI_API_KEY: "test" };
});
afterEach(() => {
db.close();
process.env = previousEnv;
});
test("QuerySqlTool", async () => {
@@ -32,8 +32,7 @@ service, and you're ready to start receiving data and triggering actions 🎉
- Copy the IFTTT key value from there. The URL is of the form
https://maker.ifttt.com/use/YOUR_IFTTT_KEY. Grab the YOUR_IFTTT_KEY value.
*/
import fetch from "node-fetch";
import { Tool } from "./base";
import { Tool } from "./base.js";
export class IFTTTWebhook extends Tool {
private url: string;
@@ -1,5 +1,4 @@
import fetch from "node-fetch";
import { Tool } from "./base";
import { Tool } from "./base.js";
class BingSerpAPI extends Tool {
name = "bing-search";
@@ -1,6 +1,6 @@
import { Parser } from "expr-eval";
import { Tool } from "./base";
import { Tool } from "./base.js";
export class Calculator extends Tool {
name = "calculator";
@@ -1,5 +1,5 @@
import { Tool } from "./base";
import { BaseChain } from "../../chains/base";
import { Tool } from "./base.js";
import { BaseChain } from "../../chains/base.js";
export class ChainTool extends Tool {
name: string;
@@ -1,5 +1,4 @@
import fetch from "node-fetch";
import { Tool } from "./base";
import { Tool } from "./base.js";
class DadJokeAPI extends Tool {
name: string;
@@ -1,4 +1,4 @@
import { Tool } from "./base";
import { Tool } from "./base.js";
export class DynamicTool extends Tool {
name: string;
+23
View File
@@ -0,0 +1,23 @@
export { SerpAPI } from "./serpapi.js";
export { Calculator } from "./calculator.js";
export { DadJokeAPI } from "./dadjokeapi.js";
export { BingSerpAPI } from "./bingserpapi.js";
export { Tool } from "./base.js";
export { DynamicTool } from "./dynamic.js";
export { IFTTTWebhook } from "./IFTTTWebhook.js";
export { ChainTool } from "./chain.js";
export {
SqlDatabase,
QuerySqlTool,
InfoSqlTool,
ListTablesSqlTool,
QueryCheckerTool,
} from "./sql.js";
export {
JsonSpec,
JsonListKeysTool,
JsonGetValueTool,
JsonObject,
Json,
} from "./json.js";
export { RequestsGetTool, RequestsPostTool } from "./requests.js";
@@ -1,5 +1,5 @@
import jsonpointer from "jsonpointer";
import { Tool } from "./base";
import { Tool } from "./base.js";
export type Json =
| string
@@ -1,4 +1,4 @@
import { Tool } from "./base";
import { Tool } from "./base.js";
export interface Headers {
[key: string]: string;
@@ -1,15 +1,6 @@
import type { getJson as GetJsonT, GoogleParameters } from "serpapi";
import { Tool } from "./base";
let getJson: typeof GetJsonT | null = null;
try {
// eslint-disable-next-line global-require,import/no-extraneous-dependencies
({ getJson } = require("serpapi"));
} catch {
// ignore error
}
import { Tool } from "./base.js";
/**
* Wrapper around SerpAPI.
@@ -27,13 +18,6 @@ export class SerpAPI extends Tool {
) {
super();
// Throw error at construction time.
if (getJson === null) {
throw new Error(
"Please install serpapi as a dependency with, e.g. `yarn add serpapi`"
);
}
if (!apiKey) {
throw new Error(
"SerpAPI API key not set. You can set it as SERPAPI_API_KEY in your .env file, or pass it to SerpAPI."
@@ -50,11 +34,7 @@ export class SerpAPI extends Tool {
* Run query through SerpAPI and parse result
*/
async call(input: string) {
if (getJson === null) {
throw new Error(
"Please install serpapi as a dependency with, e.g. `npm i serpapi`"
);
}
const { getJson } = await SerpAPI.imports();
const res = await getJson("google", {
...this.params,
api_key: this.key,
@@ -94,4 +74,17 @@ export class SerpAPI extends Tool {
description =
"a search engine. useful for when you need to answer questions about current events. input should be a search query.";
static async imports(): Promise<{
getJson: typeof GetJsonT;
}> {
try {
const { getJson } = await import("serpapi");
return { getJson };
} catch (e) {
throw new Error(
"Please install serpapi as a dependency with, e.g. `yarn add serpapi`"
);
}
}
}
@@ -1,8 +1,8 @@
import sqlite3 from "sqlite3";
import { Tool } from "./base";
import { OpenAI } from "../../llms";
import { LLMChain } from "../../chains";
import { PromptTemplate } from "../../prompts";
import { Tool } from "./base.js";
import { OpenAI } from "../../llms/index.js";
import { LLMChain } from "../../chains/index.js";
import { PromptTemplate } from "../../prompts/index.js";
export class SqlDatabase {
private db: sqlite3.Database;
@@ -1,5 +1,5 @@
import { SerializedLLMChain } from "../chains";
import { AgentInput } from "./index";
import { SerializedLLMChain } from "../chains/index.js";
import type { AgentInput } from "./index.js";
export type AgentAction = {
tool: string;
@@ -1,5 +1,5 @@
import crypto from "crypto";
import { Generation } from "./llms";
import { Generation } from "./llms/index.js";
// Takes in an arbitrary number of strings and returns a hash of them
// that can be used as a key in a cache.
@@ -1,8 +1,11 @@
import { BaseChain, ChainValues, SerializedBaseChain } from "./index";
import { BaseChain, ChainValues, SerializedBaseChain } from "./index.js";
import { TextSplitter, RecursiveCharacterTextSplitter } from "../text_splitter";
import {
TextSplitter,
RecursiveCharacterTextSplitter,
} from "../text_splitter.js";
import { resolveConfigFromFile } from "../util";
import { resolveConfigFromFile } from "../util/index.js";
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type LoadValues = Record<string, any>;
@@ -1,30 +1,28 @@
import deepcopy = require("deepcopy");
import {
import deepcopy from "deepcopy";
import type {
LLMChain,
StuffDocumentsChain,
VectorDBQAChain,
ChatVectorDBQAChain,
MapReduceDocumentsChain,
AnalyzeDocumentChain,
} from "./index";
import { BaseMemory } from "../memory";
} from "./index.js";
import { BaseMemory } from "../memory/index.js";
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type ChainValues = Record<string, any>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type LoadValues = Record<string, any>;
const chainClasses = [
LLMChain,
StuffDocumentsChain,
VectorDBQAChain,
ChatVectorDBQAChain,
MapReduceDocumentsChain,
AnalyzeDocumentChain,
];
export type SerializedBaseChain = ReturnType<
InstanceType<(typeof chainClasses)[number]>["serialize"]
InstanceType<
| typeof LLMChain
| typeof StuffDocumentsChain
| typeof VectorDBQAChain
| typeof ChatVectorDBQAChain
| typeof MapReduceDocumentsChain
| typeof AnalyzeDocumentChain
>["serialize"]
>;
export interface ChainInputs {
@@ -110,17 +108,23 @@ export abstract class BaseChain implements ChainInputs {
/**
* Load a chain from a json-like object describing it.
*/
static deserialize(
static async deserialize(
data: SerializedBaseChain,
values: LoadValues = {}
): Promise<BaseChain> {
switch (data._type) {
case "llm_chain":
case "llm_chain": {
const { LLMChain } = await import("./index.js");
return LLMChain.deserialize(data);
case "stuff_documents_chain":
}
case "stuff_documents_chain": {
const { StuffDocumentsChain } = await import("./index.js");
return StuffDocumentsChain.deserialize(data);
case "vector_db_qa":
}
case "vector_db_qa": {
const { VectorDBQAChain } = await import("./index.js");
return VectorDBQAChain.deserialize(data, values);
}
default:
throw new Error(
`Invalid prompt type in config: ${
@@ -5,14 +5,14 @@ import {
SerializedLLMChain,
loadQAChain,
LLMChain,
} from "./index";
} from "./index.js";
import { PromptTemplate } from "../prompts";
import { PromptTemplate } from "../prompts/index.js";
import { VectorStore } from "../vectorstores/base";
import { BaseLLM } from "../llms";
import { VectorStore } from "../vectorstores/base.js";
import { BaseLLM } from "../llms/index.js";
import { resolveConfigFromFile } from "../util";
import { resolveConfigFromFile } from "../util/index.js";
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type LoadValues = Record<string, any>;
@@ -4,11 +4,11 @@ import {
LLMChain,
SerializedLLMChain,
SerializedBaseChain,
} from "./index";
} from "./index.js";
import { Document } from "../document";
import { Document } from "../document.js";
import { resolveConfigFromFile } from "../util";
import { resolveConfigFromFile } from "../util/index.js";
export interface StuffDocumentsChainInput {
/** LLM Wrapper to use after formatting documents */
@@ -1,8 +1,8 @@
import { LLMChain } from "./llm_chain";
import { BaseLLM } from "../llms";
import { BasePromptTemplate, PromptTemplate } from "../prompts";
import { LLMChain } from "./llm_chain.js";
import { BaseLLM } from "../llms/index.js";
import { BasePromptTemplate, PromptTemplate } from "../prompts/index.js";
import { BaseMemory, BufferMemory } from "../memory";
import { BaseMemory, BufferMemory } from "../memory/index.js";
const defaultTemplate = `The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.
@@ -3,23 +3,27 @@ export {
ChainValues,
ChainInputs,
SerializedBaseChain,
} from "./base";
export { SerializedLLMChain, LLMChain, ConversationChain } from "./llm_chain";
} from "./base.js";
export {
SerializedLLMChain,
LLMChain,
ConversationChain,
} from "./llm_chain.js";
export {
SerializedStuffDocumentsChain,
StuffDocumentsChain,
SerializedMapReduceDocumentsChain,
MapReduceDocumentsChain,
} from "./combine_docs_chain";
} from "./combine_docs_chain.js";
export {
ChatVectorDBQAChain,
SerializedChatVectorDBQAChain,
} from "./chat_vector_db_chain";
} from "./chat_vector_db_chain.js";
export {
AnalyzeDocumentChain,
SerializedAnalyzeDocumentChain,
} from "./analyze_documents_chain";
export { VectorDBQAChain, SerializedVectorDBQAChain } from "./vector_db_qa";
export { loadChain } from "./load";
export { loadQAChain } from "./question_answering/load";
export { loadSummarizationChain } from "./summarization/load";
} from "./analyze_documents_chain.js";
export { VectorDBQAChain, SerializedVectorDBQAChain } from "./vector_db_qa.js";
export { loadChain } from "./load.js";
export { loadQAChain } from "./question_answering/load.js";
export { loadSummarizationChain } from "./summarization/load.js";
@@ -1,15 +1,15 @@
import { BaseChain, ChainValues, ChainInputs } from "./index";
import { BaseChain, ChainValues, ChainInputs } from "./index.js";
import { BaseLLM, SerializedLLM } from "../llms";
import { BaseLLM, SerializedLLM } from "../llms/index.js";
import { BaseMemory, BufferMemory } from "../memory";
import { BaseMemory, BufferMemory } from "../memory/index.js";
import {
BasePromptTemplate,
SerializedBasePromptTemplate,
PromptTemplate,
} from "../prompts";
} from "../prompts/index.js";
import { resolveConfigFromFile } from "../util";
import { resolveConfigFromFile } from "../util/index.js";
export interface LLMChainInput extends ChainInputs {
/** Prompt object to use */
@@ -1,6 +1,11 @@
import { BaseChain } from ".";
import { loadFromHub } from "../util/hub";
import { FileLoader, parseFileConfig, LoadValues, loadFromFile } from "../util";
import { BaseChain } from "./index.js";
import { loadFromHub } from "../util/hub.js";
import {
FileLoader,
parseFileConfig,
LoadValues,
loadFromFile,
} from "../util/index.js";
const loadChainFromFile: FileLoader<BaseChain> = async (
file: string,
@@ -1,15 +1,15 @@
import { BaseLLM } from "../../llms";
import { LLMChain } from "../llm_chain";
import { PromptTemplate } from "../../prompts";
import { BaseLLM } from "../../llms/index.js";
import { LLMChain } from "../llm_chain.js";
import { PromptTemplate } from "../../prompts/index.js";
import {
StuffDocumentsChain,
MapReduceDocumentsChain,
} from "../combine_docs_chain";
import { DEFAULT_QA_PROMPT } from "./stuff_prompts";
} from "../combine_docs_chain.js";
import { DEFAULT_QA_PROMPT } from "./stuff_prompts.js";
import {
COMBINE_PROMPT,
DEFAULT_COMBINE_QA_PROMPT,
} from "./map_reduce_prompts";
} from "./map_reduce_prompts.js";
interface qaChainParams {
prompt?: PromptTemplate;
@@ -1,5 +1,5 @@
/* eslint-disable */
import { PromptTemplate } from "../../prompts";
import { PromptTemplate } from "../../prompts/index.js";
const qa_template = `Use the following portion of a long document to see if any of the text is relevant to answer the question.
Return any relevant text verbatim.
@@ -1,5 +1,5 @@
/* eslint-disable */
import { PromptTemplate } from "../../prompts";
import { PromptTemplate } from "../../prompts/index.js";
export const DEFAULT_QA_PROMPT = new PromptTemplate({
template:
@@ -1,10 +1,10 @@
import { test } from "@jest/globals";
import { OpenAI } from "../../../llms/openai";
import { loadQAChain } from "../load";
import { Document } from "../../../document";
import { OpenAI } from "../../../llms/openai.js";
import { loadQAChain } from "../load.js";
import { Document } from "../../../document.js";
test("Test loadQAChain", async () => {
const model = new OpenAI({});
const model = new OpenAI({ modelName: "text-ada-001" });
const chain = loadQAChain(model);
const docs = [
new Document({ pageContent: "foo" }),
@@ -16,7 +16,7 @@ test("Test loadQAChain", async () => {
});
test("Test loadQAChain map_reduce", async () => {
const model = new OpenAI({});
const model = new OpenAI({ modelName: "text-ada-001" });
const chain = loadQAChain(model, { type: "map_reduce" });
const docs = [
new Document({ pageContent: "foo" }),
@@ -1,11 +1,11 @@
import { BaseLLM } from "../../llms";
import { LLMChain } from "../llm_chain";
import { PromptTemplate } from "../../prompts";
import { BaseLLM } from "../../llms/index.js";
import { LLMChain } from "../llm_chain.js";
import { PromptTemplate } from "../../prompts/index.js";
import {
StuffDocumentsChain,
MapReduceDocumentsChain,
} from "../combine_docs_chain";
import { DEFAULT_PROMPT } from "./stuff_prompts";
} from "../combine_docs_chain.js";
import { DEFAULT_PROMPT } from "./stuff_prompts.js";
interface summarizationChainParams {
prompt?: PromptTemplate;
@@ -1,5 +1,5 @@
/* eslint-disable */
import { PromptTemplate } from "../../prompts";
import { PromptTemplate } from "../../prompts/index.js";
const template = `Write a concise summary of the following:
@@ -1,10 +1,10 @@
import { test } from "@jest/globals";
import { OpenAI } from "../../../llms/openai";
import { loadSummarizationChain } from "../load";
import { Document } from "../../../document";
import { OpenAI } from "../../../llms/openai.js";
import { loadSummarizationChain } from "../load.js";
import { Document } from "../../../document.js";
test("Test loadSummzationChain", async () => {
const model = new OpenAI({});
const model = new OpenAI({ modelName: "text-ada-001" });
const chain = loadSummarizationChain(model);
const docs = [
new Document({ pageContent: "foo" }),
@@ -16,7 +16,7 @@ test("Test loadSummzationChain", async () => {
});
test("Test loadQAChain map_reduce", async () => {
const model = new OpenAI({});
const model = new OpenAI({ modelName: "text-ada-001" });
const chain = loadSummarizationChain(model, { type: "map_reduce" });
const docs = [
new Document({ pageContent: "foo" }),
@@ -1,14 +1,14 @@
import { test } from "@jest/globals";
import { OpenAI } from "../../llms/openai";
import { PromptTemplate } from "../../prompts";
import { LLMChain } from "../llm_chain";
import { StuffDocumentsChain } from "../combine_docs_chain";
import { ChatVectorDBQAChain } from "../chat_vector_db_chain";
import { HNSWLib } from "../../vectorstores/hnswlib";
import { OpenAIEmbeddings } from "../../embeddings";
import { OpenAI } from "../../llms/openai.js";
import { PromptTemplate } from "../../prompts/index.js";
import { LLMChain } from "../llm_chain.js";
import { StuffDocumentsChain } from "../combine_docs_chain.js";
import { ChatVectorDBQAChain } from "../chat_vector_db_chain.js";
import { HNSWLib } from "../../vectorstores/hnswlib.js";
import { OpenAIEmbeddings } from "../../embeddings/index.js";
test("Test ChatVectorDBQAChain", async () => {
const model = new OpenAI({});
const model = new OpenAI({ modelName: "text-ada-001" });
const prompt = PromptTemplate.fromTemplate(
"Print {question}, and ignore {chat_history}"
);
@@ -32,7 +32,7 @@ test("Test ChatVectorDBQAChain", async () => {
});
test("Test ChatVectorDBQAChain from LLM", async () => {
const model = new OpenAI({});
const model = new OpenAI({ modelName: "text-ada-001" });
const vectorStore = await HNSWLib.fromTexts(
["Hello world", "Bye bye", "hello nice world", "bye", "hi"],
[{ id: 2 }, { id: 1 }, { id: 3 }, { id: 4 }, { id: 5 }],
@@ -1,14 +1,14 @@
import { test } from "@jest/globals";
import { OpenAI } from "../../llms/openai";
import { PromptTemplate } from "../../prompts";
import { LLMChain } from "../llm_chain";
import { loadChain } from "../load";
import { StuffDocumentsChain } from "../combine_docs_chain";
import { Document } from "../../document";
import { loadQAChain } from "../question_answering/load";
import { OpenAI } from "../../llms/openai.js";
import { PromptTemplate } from "../../prompts/index.js";
import { LLMChain } from "../llm_chain.js";
import { loadChain } from "../load.js";
import { StuffDocumentsChain } from "../combine_docs_chain.js";
import { Document } from "../../document.js";
import { loadQAChain } from "../question_answering/load.js";
test("Test StuffDocumentsChain", async () => {
const model = new OpenAI({});
const model = new OpenAI({ modelName: "text-ada-001" });
const prompt = new PromptTemplate({
template: "Print {foo}",
inputVariables: ["foo"],
@@ -28,7 +28,7 @@ test("Test StuffDocumentsChain", async () => {
});
test("Test MapReduceDocumentsChain with QA chain", async () => {
const model = new OpenAI({ temperature: 0 });
const model = new OpenAI({ temperature: 0, modelName: "text-ada-001" });
const chain = loadQAChain(model, { type: "map_reduce" });
const docs = [
new Document({ pageContent: "harrison went to harvard" }),
@@ -1,7 +1,7 @@
import { test, expect } from "@jest/globals";
import { Document } from "../../document";
import { BaseLLM, LLMResult } from "../../llms";
import { loadQAChain } from "../question_answering/load";
import { Document } from "../../document.js";
import { BaseLLM, LLMResult } from "../../llms/index.js";
import { loadQAChain } from "../question_answering/load.js";
test("Test MapReduceDocumentsChain", async () => {
let nrMapCalls = 0;
@@ -1,11 +1,11 @@
import { test } from "@jest/globals";
import { OpenAI } from "../../llms/openai";
import { PromptTemplate } from "../../prompts";
import { LLMChain, ConversationChain } from "../llm_chain";
import { loadChain } from "../load";
import { OpenAI } from "../../llms/openai.js";
import { PromptTemplate } from "../../prompts/index.js";
import { LLMChain, ConversationChain } from "../llm_chain.js";
import { loadChain } from "../load.js";
test("Test OpenAI", async () => {
const model = new OpenAI({});
const model = new OpenAI({ modelName: "text-ada-001" });
const prompt = new PromptTemplate({
template: "Print {foo}",
inputVariables: ["foo"],
@@ -16,7 +16,7 @@ test("Test OpenAI", async () => {
});
test("Test run method", async () => {
const model = new OpenAI({});
const model = new OpenAI({ modelName: "text-ada-001" });
const prompt = new PromptTemplate({
template: "Print {foo}",
inputVariables: ["foo"],
@@ -27,7 +27,7 @@ test("Test run method", async () => {
});
test("Test apply", async () => {
const model = new OpenAI({});
const model = new OpenAI({ modelName: "text-ada-001" });
const prompt = new PromptTemplate({
template: "Print {foo}",
inputVariables: ["foo"],
@@ -44,7 +44,7 @@ test("Load chain from hub", async () => {
});
test("Test ConversationChain", async () => {
const model = new OpenAI({});
const model = new OpenAI({ modelName: "text-ada-001" });
const chain = new ConversationChain({ llm: model });
const res = await chain.call({ input: "my favorite color" });
console.log({ res });
@@ -1,15 +1,15 @@
import { test } from "@jest/globals";
import { OpenAI } from "../../llms/openai";
import { PromptTemplate } from "../../prompts";
import { LLMChain } from "../llm_chain";
import { loadChain } from "../load";
import { StuffDocumentsChain } from "../combine_docs_chain";
import { VectorDBQAChain } from "../vector_db_qa";
import { HNSWLib } from "../../vectorstores/hnswlib";
import { OpenAIEmbeddings } from "../../embeddings";
import { OpenAI } from "../../llms/openai.js";
import { PromptTemplate } from "../../prompts/index.js";
import { LLMChain } from "../llm_chain.js";
import { loadChain } from "../load.js";
import { StuffDocumentsChain } from "../combine_docs_chain.js";
import { VectorDBQAChain } from "../vector_db_qa.js";
import { HNSWLib } from "../../vectorstores/hnswlib.js";
import { OpenAIEmbeddings } from "../../embeddings/index.js";
test("Test VectorDBQAChain", async () => {
const model = new OpenAI({});
const model = new OpenAI({ modelName: "text-ada-001" });
const prompt = new PromptTemplate({
template: "Print {foo}",
inputVariables: ["foo"],
@@ -33,7 +33,7 @@ test("Test VectorDBQAChain", async () => {
});
test("Test VectorDBQAChain from LLM", async () => {
const model = new OpenAI({});
const model = new OpenAI({ modelName: "text-ada-001" });
const vectorStore = await HNSWLib.fromTexts(
["Hello world", "Bye bye", "hello nice world", "bye", "hi"],
[{ id: 2 }, { id: 1 }, { id: 3 }, { id: 4 }, { id: 5 }],
@@ -3,12 +3,12 @@ import {
ChainValues,
SerializedBaseChain,
loadQAChain,
} from "./index";
} from "./index.js";
import { VectorStore } from "../vectorstores/base";
import { BaseLLM } from "../llms";
import { VectorStore } from "../vectorstores/base.js";
import { BaseLLM } from "../llms/index.js";
import { resolveConfigFromFile } from "../util";
import { resolveConfigFromFile } from "../util/index.js";
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type LoadValues = Record<string, any>;
@@ -1,4 +1,4 @@
import { Document } from "../document";
import { Document } from "../document.js";
export abstract class Docstore {
abstract search(search: string): Document | string;
@@ -1,5 +1,5 @@
import { Document } from "../document";
import { Docstore } from "./base";
import { Document } from "../document.js";
import { Docstore } from "./base.js";
export class InMemoryDocstore extends Docstore {
_docs: Map<string, Document>;
+3
View File
@@ -0,0 +1,3 @@
export { Document } from "../document.js";
export { Docstore } from "./base.js";
export { InMemoryDocstore } from "./in_memory.js";
@@ -1,5 +1,8 @@
import { RecursiveCharacterTextSplitter, TextSplitter } from "../text_splitter";
import { Document } from "../document";
import {
RecursiveCharacterTextSplitter,
TextSplitter,
} from "../text_splitter.js";
import { Document } from "../document.js";
export interface DocumentLoader {
load(): Promise<Document[]>;
@@ -1,7 +1,7 @@
import type { CheerioAPI, load as LoadT } from "cheerio";
import { Document } from "../document";
import { BaseDocumentLoader } from "./base";
import type { DocumentLoader } from "./base";
import { Document } from "../document.js";
import { BaseDocumentLoader } from "./base.js";
import type { DocumentLoader } from "./base.js";
let load: typeof LoadT | null = null;
@@ -1,5 +1,5 @@
import { Document } from "../document";
import { CheerioWebBaseLoader } from "./cheerio_web_base";
import { Document } from "../document.js";
import { CheerioWebBaseLoader } from "./cheerio_web_base.js";
export class CollegeConfidentialLoader extends CheerioWebBaseLoader {
constructor(webPath: string) {
@@ -1,6 +1,6 @@
import type { CheerioAPI } from "cheerio";
import { Document } from "../document";
import { CheerioWebBaseLoader } from "./cheerio_web_base";
import { Document } from "../document.js";
import { CheerioWebBaseLoader } from "./cheerio_web_base.js";
interface GitbookLoaderParams {
shouldLoadAllPaths?: boolean;
@@ -1,6 +1,6 @@
import type { CheerioAPI } from "cheerio";
import { Document } from "../document";
import { CheerioWebBaseLoader } from "./cheerio_web_base";
import { Document } from "../document.js";
import { CheerioWebBaseLoader } from "./cheerio_web_base.js";
export class HNLoader extends CheerioWebBaseLoader {
constructor(public webPath: string) {
@@ -1,5 +1,5 @@
import { Document } from "../document";
import { CheerioWebBaseLoader } from "./cheerio_web_base";
import { Document } from "../document.js";
import { CheerioWebBaseLoader } from "./cheerio_web_base.js";
export class IMSDBLoader extends CheerioWebBaseLoader {
constructor(public webPath: string) {
+9
View File
@@ -0,0 +1,9 @@
export type { DocumentLoader } from "./base.js";
export { BaseDocumentLoader } from "./base.js";
export { CheerioWebBaseLoader } from "./cheerio_web_base.js";
export { CollegeConfidentialLoader } from "./college_confidential.js";
export { GitbookLoader } from "./gitbook.js";
export { HNLoader } from "./hn.js";
export { IMSDBLoader } from "./imsdb.js";
export { SRTLoader } from "./srt.js";
export { TextLoader } from "./text.js";
@@ -1,29 +1,33 @@
import type { readFile as ReadFileT } from "fs/promises";
import type SRTParserT from "srt-parser-2";
import { Document } from "../document";
import { BaseDocumentLoader } from "./base";
let readFile: typeof ReadFileT | null = null;
let SRTParser2: typeof SRTParserT | null = null;
try {
// eslint-disable-next-line global-require,import/no-extraneous-dependencies
({ readFile } = require("fs/promises"));
// eslint-disable-next-line global-require,import/no-extraneous-dependencies
({ SRTParser2 } = require("srt-parser-2"));
} catch {
// ignore error, will be throw in constructor
}
import { Document } from "../document.js";
import { BaseDocumentLoader } from "./base.js";
export class SRTLoader extends BaseDocumentLoader {
constructor(public filePath: string) {
super();
/**
* Throw error at construction time
* if fs/promises is not installed.
*/
if (readFile === null) {
this.filePath = filePath;
}
public async load(): Promise<Document[]> {
const { readFile, SRTParser2 } = await SRTLoader.imports();
const file = await readFile(this.filePath, "utf8");
const parser = new SRTParser2();
const srts = parser.fromSrt(file);
const text = srts.map((srt) => srt.text).join(" ");
const metadata = { source: this.filePath };
return [new Document({ pageContent: text, metadata })];
}
static async imports(): Promise<{
readFile: typeof ReadFileT;
SRTParser2: typeof SRTParserT.default;
}> {
let readFile: typeof ReadFileT | null = null;
try {
readFile = (await import("fs/promises")).readFile;
} catch (e) {
const {
isBrowser,
isNode,
@@ -51,33 +55,14 @@ export class SRTLoader extends BaseDocumentLoader {
);
}
/**
* Throw error at construction time
* if srt-parser-2 is not installed.
*/
if (SRTParser2 === null) {
let SRTParser2: typeof SRTParserT.default | null = null;
try {
SRTParser2 = (await import("srt-parser-2")).default.default;
} catch (e) {
throw new Error(
"Please install srt-parser-2 as a dependency with, e.g. `yarn add srt-parser-2`"
);
}
}
public async load(): Promise<Document[]> {
if (readFile === null) {
throw new Error("Failed to load fs/promises.");
}
if (SRTParser2 === null) {
throw new Error(
"Please install srt-parser-2 as a dependency with, e.g. `yarn add srt-parser-2`"
);
}
const file = await readFile(this.filePath, "utf8");
const parser = new SRTParser2();
const srts = parser.fromSrt(file);
const text = srts.map((srt) => srt.text).join(" ");
const metadata = { source: this.filePath };
return [new Document({ pageContent: text, metadata })];
return { readFile, SRTParser2 };
}
}
@@ -1,6 +1,6 @@
import type { readFile as ReadFileT } from "fs/promises";
import { Document } from "../document";
import { BaseDocumentLoader } from "./base";
import { Document } from "../document.js";
import { BaseDocumentLoader } from "./base.js";
let readFile: typeof ReadFileT | null = null;
@@ -1,4 +1,4 @@
import { Embeddings } from "./base";
import { Embeddings } from "./base.js";
export class FakeEmbeddings extends Embeddings {
embedDocuments(documents: string[]): Promise<number[][]> {
+1
View File
@@ -0,0 +1 @@
export { OpenAIEmbeddings } from "./openai.js";
@@ -4,18 +4,9 @@ import type {
CreateEmbeddingRequest,
} from "openai";
import { backOff } from "exponential-backoff";
import { chunkArray } from "../util";
import { Embeddings } from "./base";
let Configuration: typeof ConfigurationT | null = null;
let OpenAIApi: typeof OpenAIApiT | null = null;
try {
// eslint-disable-next-line global-require,import/no-extraneous-dependencies
({ Configuration, OpenAIApi } = require("openai"));
} catch {
// ignore error
}
import type fetchAdapterT from "../util/axios-fetch-adapter.js";
import { chunkArray } from "../util/index.js";
import { Embeddings } from "./base.js";
interface ModelParams {
modelName: string;
@@ -28,6 +19,8 @@ export class OpenAIEmbeddings extends Embeddings implements ModelParams {
maxRetries = 6;
private apiKey: string;
private client: OpenAIApiT;
constructor(
@@ -39,18 +32,16 @@ export class OpenAIEmbeddings extends Embeddings implements ModelParams {
}
) {
super();
if (Configuration === null || OpenAIApi === null) {
throw new Error(
"Please install openai as a dependency with, e.g. `npm install -S openai`"
);
const apiKey = fields?.openAIApiKey ?? process.env.OPENAI_API_KEY;
if (!apiKey) {
throw new Error("OpenAI API key not found");
}
this.modelName = fields?.modelName ?? this.modelName;
this.batchSize = fields?.batchSize ?? this.batchSize;
const clientConfig = new Configuration({
apiKey: fields?.openAIApiKey ?? process.env.OPENAI_API_KEY,
});
this.client = new OpenAIApi(clientConfig);
this.apiKey = apiKey;
this.maxRetries = fields?.maxRetries ?? this.maxRetries;
}
async embedDocuments(texts: string[]): Promise<number[][]> {
@@ -80,7 +71,16 @@ export class OpenAIEmbeddings extends Embeddings implements ModelParams {
return data.data[0].embedding;
}
private embeddingWithRetry(request: CreateEmbeddingRequest) {
private async embeddingWithRetry(request: CreateEmbeddingRequest) {
if (!this.client) {
const { Configuration, OpenAIApi, fetchAdapter } =
await OpenAIEmbeddings.imports();
const clientConfig = new Configuration({
apiKey: this.apiKey,
baseOptions: { adapter: fetchAdapter },
});
this.client = new OpenAIApi(clientConfig);
}
const makeCompletionRequest = () => this.client.createEmbedding(request);
return backOff(makeCompletionRequest, {
startingDelay: 4,
@@ -88,4 +88,23 @@ export class OpenAIEmbeddings extends Embeddings implements ModelParams {
numOfAttempts: this.maxRetries,
});
}
static async imports(): Promise<{
Configuration: typeof ConfigurationT;
OpenAIApi: typeof OpenAIApiT;
fetchAdapter: typeof fetchAdapterT;
}> {
try {
const { Configuration, OpenAIApi } = await import("openai");
const { default: fetchAdapter } = await import(
"../util/axios-fetch-adapter.js"
);
return { Configuration, OpenAIApi, fetchAdapter };
} catch (err) {
console.error(err);
throw new Error(
"Please install openai as a dependency with, e.g. `npm install -S openai`"
);
}
}
}
@@ -1,5 +1,5 @@
import { test, expect } from "@jest/globals";
import { OpenAIEmbeddings } from "../openai";
import { OpenAIEmbeddings } from "../openai.js";
test("Test OpenAIEmbeddings.embedQuery", async () => {
const embeddings = new OpenAIEmbeddings();
+8
View File
@@ -0,0 +1,8 @@
export {
PromptTemplate,
BasePromptTemplate,
FewShotPromptTemplate,
} from "./prompts/index.js";
export { LLMChain } from "./chains/index.js";
export { OpenAI } from "./llms/index.js";
@@ -1,8 +1,8 @@
import { encode } from "gpt-3-encoder";
import PQueue from "p-queue";
import { LLMCallbackManager, LLMResult, OpenAI } from "./index";
import { BaseCache, getKey, InMemoryCache } from "../cache";
import { LLMCallbackManager, LLMResult } from "./index.js";
import { BaseCache, getKey, InMemoryCache } from "../cache.js";
const getCallbackManager = (): LLMCallbackManager => ({
handleStart: (..._args) => {
@@ -181,7 +181,7 @@ export abstract class BaseLLM {
static async deserialize(data: SerializedLLM): Promise<BaseLLM> {
const { _type, ...rest } = data;
const Cls = {
openai: OpenAI,
openai: (await import("./openai.js")).OpenAI,
}[_type];
if (Cls === undefined) {
throw new Error(`Cannot load LLM with type ${_type}`);

Some files were not shown because too many files have changed in this diff Show More