forked from langchain-ai/langchainjs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added PyInterpreterTool (langchain-ai#3090)
* Added PyInterpreterTool * Updated PyInterpreterTool * Moved PythonInterpreterTool to tools/experimental * Move to experimental, fix race condition in constructor * Fix lint + test * Adds docs + example --------- Co-authored-by: Mish Ushakov <[email protected]> Co-authored-by: jacoblee93 <[email protected]>
- Loading branch information
1 parent
db7da8d
commit 9c3120a
Showing
11 changed files
with
357 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
--- | ||
hide_table_of_contents: true | ||
--- | ||
|
||
import CodeBlock from "@theme/CodeBlock"; | ||
|
||
# Python interpreter tool | ||
|
||
:::warning | ||
This tool executes code and can potentially perform destructive actions. Be careful that you trust any code passed to it! | ||
::: | ||
|
||
LangChain offers an experimental tool for executing arbitrary Python code. | ||
This can be useful in combination with an LLM that can generate code to perform more powerful computations. | ||
|
||
## Usage | ||
|
||
import ToolExample from "@examples/tools/pyinterpreter.ts"; | ||
|
||
<CodeBlock language="typescript">{ToolExample}</CodeBlock> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { ChatPromptTemplate } from "langchain/prompts"; | ||
import { OpenAI } from "langchain/llms/openai"; | ||
import { PythonInterpreterTool } from "langchain/experimental/tools/pyinterpreter"; | ||
import { StringOutputParser } from "langchain/schema/output_parser"; | ||
|
||
const prompt = ChatPromptTemplate.fromTemplate( | ||
`Generate python code that does {input}. Do not generate anything else.` | ||
); | ||
|
||
const model = new OpenAI({}); | ||
|
||
const interpreter = await PythonInterpreterTool.initialize({ | ||
indexURL: "../node_modules/pyodide", | ||
}); | ||
const chain = prompt | ||
.pipe(model) | ||
.pipe(new StringOutputParser()) | ||
.pipe(interpreter); | ||
|
||
const result = await chain.invoke({ | ||
input: `prints "Hello LangChain"`, | ||
}); | ||
|
||
console.log(JSON.parse(result).stdout); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,239 @@ | ||
import { loadPyodide, type PyodideInterface } from "pyodide"; | ||
import { Tool, ToolParams } from "../../tools/base.js"; | ||
|
||
export type PythonInterpreterToolParams = Parameters<typeof loadPyodide>[0] & | ||
ToolParams & { | ||
instance: PyodideInterface; | ||
}; | ||
|
||
export class PythonInterpreterTool extends Tool { | ||
static lc_name() { | ||
return "PythonInterpreterTool"; | ||
} | ||
|
||
name = "python_interpreter"; | ||
|
||
description = `Evaluates python code in a sandbox environment. The environment resets on every execution. You must send the whole script every time and print your outputs. Script should be pure python code that can be evaluated. Packages available: | ||
${this.availableDefaultPackages}`; | ||
|
||
pyodideInstance: PyodideInterface; | ||
|
||
stdout = ""; | ||
|
||
stderr = ""; | ||
|
||
constructor(options: PythonInterpreterToolParams) { | ||
super(options); | ||
this.pyodideInstance = options.instance; | ||
this.pyodideInstance.setStderr({ | ||
batched: (text: string) => { | ||
this.stderr += text; | ||
}, | ||
}); | ||
|
||
this.pyodideInstance.setStdout({ | ||
batched: (text: string) => { | ||
this.stdout += text; | ||
}, | ||
}); | ||
} | ||
|
||
async addPackage(packageName: string) { | ||
await this.pyodideInstance.loadPackage(packageName); | ||
this.description += `, ${packageName}`; | ||
} | ||
|
||
get availableDefaultPackages(): string { | ||
return [ | ||
"asciitree", | ||
"astropy", | ||
"atomicwrites", | ||
"attrs", | ||
"autograd", | ||
"awkward-cpp", | ||
"bcrypt", | ||
"beautifulsoup4", | ||
"biopython", | ||
"bitarray", | ||
"bitstring", | ||
"bleach", | ||
"bokeh", | ||
"boost-histogram", | ||
"brotli", | ||
"cachetools", | ||
"Cartopy", | ||
"cbor-diag", | ||
"certifi", | ||
"cffi", | ||
"cffi_example", | ||
"cftime", | ||
"click", | ||
"cligj", | ||
"cloudpickle", | ||
"cmyt", | ||
"colorspacious", | ||
"contourpy", | ||
"coolprop", | ||
"coverage", | ||
"cramjam", | ||
"cryptography", | ||
"cssselect", | ||
"cycler", | ||
"cytoolz", | ||
"decorator", | ||
"demes", | ||
"deprecation", | ||
"distlib", | ||
"docutils", | ||
"exceptiongroup", | ||
"fastparquet", | ||
"fiona", | ||
"fonttools", | ||
"freesasa", | ||
"fsspec", | ||
"future", | ||
"galpy", | ||
"gensim", | ||
"geopandas", | ||
"gmpy2", | ||
"gsw", | ||
"h5py", | ||
"html5lib", | ||
"idna", | ||
"igraph", | ||
"imageio", | ||
"iniconfig", | ||
"jedi", | ||
"Jinja2", | ||
"joblib", | ||
"jsonschema", | ||
"kiwisolver", | ||
"lazy-object-proxy", | ||
"lazy_loader", | ||
"lightgbm", | ||
"logbook", | ||
"lxml", | ||
"MarkupSafe", | ||
"matplotlib", | ||
"matplotlib-pyodide", | ||
"micropip", | ||
"mne", | ||
"more-itertools", | ||
"mpmath", | ||
"msgpack", | ||
"msprime", | ||
"multidict", | ||
"munch", | ||
"mypy", | ||
"netcdf4", | ||
"networkx", | ||
"newick", | ||
"nlopt", | ||
"nltk", | ||
"nose", | ||
"numcodecs", | ||
"numpy", | ||
"opencv-python", | ||
"optlang", | ||
"orjson", | ||
"packaging", | ||
"pandas", | ||
"parso", | ||
"patsy", | ||
"peewee", | ||
"Pillow", | ||
"pillow_heif", | ||
"pkgconfig", | ||
"pluggy", | ||
"protobuf", | ||
"py", | ||
"pyb2d", | ||
"pyclipper", | ||
"pycparser", | ||
"pycryptodome", | ||
"pydantic", | ||
"pyerfa", | ||
"Pygments", | ||
"pyheif", | ||
"pyinstrument", | ||
"pynacl", | ||
"pyodide-http", | ||
"pyodide-tblib", | ||
"pyparsing", | ||
"pyproj", | ||
"pyrsistent", | ||
"pyshp", | ||
"pytest", | ||
"pytest-benchmark", | ||
"python-dateutil", | ||
"python-magic", | ||
"python-sat", | ||
"python_solvespace", | ||
"pytz", | ||
"pywavelets", | ||
"pyxel", | ||
"pyyaml", | ||
"rebound", | ||
"reboundx", | ||
"regex", | ||
"retrying", | ||
"RobotRaconteur", | ||
"ruamel.yaml", | ||
"rust-panic-test", | ||
"scikit-image", | ||
"scikit-learn", | ||
"scipy", | ||
"screed", | ||
"setuptools", | ||
"shapely", | ||
"simplejson", | ||
"six", | ||
"smart_open", | ||
"soupsieve", | ||
"sourmash", | ||
"sparseqr", | ||
"sqlalchemy", | ||
"statsmodels", | ||
"svgwrite", | ||
"swiglpk", | ||
"sympy", | ||
"termcolor", | ||
"texttable", | ||
"threadpoolctl", | ||
"tomli", | ||
"tomli-w", | ||
"toolz", | ||
"tqdm", | ||
"traits", | ||
"tskit", | ||
"typing-extensions", | ||
"uncertainties", | ||
"unyt", | ||
"webencodings", | ||
"wordcloud", | ||
"wrapt", | ||
"xarray", | ||
"xgboost", | ||
"xlrd", | ||
"xyzservices", | ||
"yarl", | ||
"yt", | ||
"zarr", | ||
].join(", "); | ||
} | ||
|
||
static async initialize( | ||
options: Omit<PythonInterpreterToolParams, "instance"> | ||
) { | ||
const instance = await loadPyodide(options); | ||
return new this({ ...options, instance }); | ||
} | ||
|
||
async _call(script: string) { | ||
this.stdout = ""; | ||
this.stderr = ""; | ||
|
||
await this.pyodideInstance.runPythonAsync(script); | ||
return JSON.stringify({ stdout: this.stdout, stderr: this.stderr }); | ||
} | ||
} |
29 changes: 29 additions & 0 deletions
29
langchain/src/experimental/tools/tests/pyinterpreter.int.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { test, expect } from "@jest/globals"; | ||
import { StringOutputParser } from "../../../schema/output_parser.js"; | ||
import { OpenAI } from "../../../llms/openai.js"; | ||
import { PromptTemplate } from "../../../prompts/index.js"; | ||
import { PythonInterpreterTool } from "../pyinterpreter.js"; | ||
|
||
describe("Python Interpreter testsuite", () => { | ||
test("hello langchain", async () => { | ||
const prompt = PromptTemplate.fromTemplate( | ||
`Can you generate python code that: {input}? Do not generate anything else.` | ||
); | ||
|
||
const model = new OpenAI({}); | ||
|
||
const interpreter = await PythonInterpreterTool.initialize({ | ||
indexURL: "../node_modules/pyodide", | ||
}); | ||
const chain = prompt | ||
.pipe(model) | ||
.pipe(new StringOutputParser()) | ||
.pipe(interpreter); | ||
|
||
const result = await chain.invoke({ | ||
input: `prints "Hello LangChain"`, | ||
}); | ||
|
||
expect(JSON.parse(result).stdout).toBe("Hello LangChain"); | ||
}); | ||
}); |
Oops, something went wrong.