diff --git a/docs/docs/integrations/tools/riza.ipynb b/docs/docs/integrations/tools/riza.ipynb new file mode 100644 index 00000000000..a41fbd54ea3 --- /dev/null +++ b/docs/docs/integrations/tools/riza.ipynb @@ -0,0 +1,183 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "7d143c73", + "metadata": {}, + "source": [ + "# Riza Code Interpreter\n", + "\n", + "> The Riza Code Interpreter is a WASM-based isolated environment for running Python or JavaScript generated by AI agents.\n", + "\n", + "In this notebook we'll create an example of an agent that uses Python to solve a problem that an LLM can't solve on its own:\n", + "counting the number of 'r's in the word \"strawberry.\"\n", + "\n", + "Before you get started grab an API key from the [Riza dashboard](https://dashboard.riza.io). For more guides and a full API reference\n", + "head over to the [Riza Code Interpreter API documentation](https://docs.riza.io)." + ] + }, + { + "cell_type": "markdown", + "id": "894aa87a", + "metadata": {}, + "source": [ + "Make sure you have the necessary dependencies installed." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8265cf7f", + "metadata": {}, + "outputs": [], + "source": [ + "%pip install --upgrade --quiet langchain-community rizaio" + ] + }, + { + "cell_type": "markdown", + "id": "e085eb51", + "metadata": {}, + "source": [ + "Set up your API keys as an environment variable." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "45ba8936", + "metadata": {}, + "outputs": [], + "source": [ + "%env ANTHROPIC_API_KEY=\n", + "%env RIZA_API_KEY=" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "efe26fd9-6e33-4f5f-b49b-ea74fa6c4915", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain_community.tools.riza.command import ExecPython" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "cd5b952e", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.agents import AgentExecutor, create_tool_calling_agent\n", + "from langchain_anthropic import ChatAnthropic\n", + "from langchain_core.prompts import ChatPromptTemplate" + ] + }, + { + "cell_type": "markdown", + "id": "7bd0b610", + "metadata": {}, + "source": [ + "Initialize the `ExecPython` tool." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "32f1543f", + "metadata": {}, + "outputs": [], + "source": [ + "tools = [ExecPython()]" + ] + }, + { + "cell_type": "markdown", + "id": "24f952d5", + "metadata": {}, + "source": [ + "Initialize an agent using Anthropic's Claude Haiku model." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "71831ea8", + "metadata": {}, + "outputs": [], + "source": [ + "llm = ChatAnthropic(model=\"claude-3-haiku-20240307\", temperature=0)\n", + "\n", + "prompt_template = ChatPromptTemplate.from_messages(\n", + " [\n", + " (\n", + " \"system\",\n", + " \"You are a helpful assistant. Make sure to use a tool if you need to solve a problem.\",\n", + " ),\n", + " (\"human\", \"{input}\"),\n", + " (\"placeholder\", \"{agent_scratchpad}\"),\n", + " ]\n", + ")\n", + "\n", + "agent = create_tool_calling_agent(llm, tools, prompt_template)\n", + "agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "36b24036", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n", + "\u001b[32;1m\u001b[1;3m\n", + "Invoking: `riza_exec_python` with `{'code': 'word = \"strawberry\"\\nprint(word.count(\"r\"))'}`\n", + "responded: [{'id': 'toolu_01JwPLAAqqCNCjVuEnK8Fgut', 'input': {}, 'name': 'riza_exec_python', 'type': 'tool_use', 'index': 0, 'partial_json': '{\"code\": \"word = \\\\\"strawberry\\\\\"\\\\nprint(word.count(\\\\\"r\\\\\"))\"}'}]\n", + "\n", + "\u001b[0m\u001b[36;1m\u001b[1;3m3\n", + "\u001b[0m\u001b[32;1m\u001b[1;3m[{'text': '\\n\\nThe word \"strawberry\" contains 3 \"r\" characters.', 'type': 'text', 'index': 0}]\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "\n", + "The word \"strawberry\" contains 3 \"r\" characters.\n" + ] + } + ], + "source": [ + "# Ask a tough question\n", + "result = agent_executor.invoke({\"input\": \"how many rs are in strawberry?\"})\n", + "print(result[\"output\"][0][\"text\"])" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/libs/community/langchain_community/tools/riza/__init__.py b/libs/community/langchain_community/tools/riza/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/libs/community/langchain_community/tools/riza/command.py b/libs/community/langchain_community/tools/riza/command.py new file mode 100644 index 00000000000..ce9451121f0 --- /dev/null +++ b/libs/community/langchain_community/tools/riza/command.py @@ -0,0 +1,95 @@ +""" +Tool implementations for the Riza (https://riza.io) code interpreter API. + +Documentation: https://docs.riza.io +API keys: https://dashboard.riza.io +""" + +from typing import Any, Optional, Type + +from langchain_core.callbacks import ( + CallbackManagerForToolRun, +) +from langchain_core.pydantic_v1 import BaseModel, Field +from langchain_core.tools import BaseTool, ToolException + + +class ExecPythonInput(BaseModel): + code: str = Field(description="the Python code to execute") + + +class ExecPython(BaseTool): + """A tool implementation to execute Python via Riza's Code Interpreter API.""" + + name: str = "riza_exec_python" + description: str = """Execute Python code to solve problems. + + The Python runtime does not have filesystem access. You can use the httpx + or requests library to make HTTP requests. Always print output to stdout.""" + args_schema: Type[BaseModel] = ExecPythonInput + handle_tool_error: bool = True + + client: Any = None + + def __init__(self, **kwargs: Any) -> None: + try: + from rizaio import Riza + except ImportError as e: + raise ImportError( + "Couldn't import the `rizaio` package. " + "Try running `pip install rizaio`." + ) from e + super().__init__(**kwargs) + self.client = Riza() + + def _run( + self, code: str, run_manager: Optional[CallbackManagerForToolRun] = None + ) -> str: + output = self.client.command.exec(language="PYTHON", code=code) + if output.exit_code > 0: + raise ToolException( + f"Riza code execution returned a non-zero exit code. " + f"The output captured from stderr was:\n{output.stderr}" + ) + return output.stdout + + +class ExecJavaScriptInput(BaseModel): + code: str = Field(description="the JavaScript code to execute") + + +class ExecJavaScript(BaseTool): + """A tool implementation to execute JavaScript via Riza's Code Interpreter API.""" + + name: str = "riza_exec_javascript" + description: str = """Execute JavaScript code to solve problems. + + The JavaScript runtime does not have filesystem access, but can use fetch + to make HTTP requests and does include the global JSON object. Always print + output to stdout.""" + args_schema: Type[BaseModel] = ExecJavaScriptInput + handle_tool_error: bool = True + + client: Any = None + + def __init__(self, **kwargs: Any) -> None: + try: + from rizaio import Riza + except ImportError as e: + raise ImportError( + "Couldn't import the `rizaio` package. " + "Try running `pip install rizaio`." + ) from e + super().__init__(**kwargs) + self.client = Riza() + + def _run( + self, code: str, run_manager: Optional[CallbackManagerForToolRun] = None + ) -> str: + output = self.client.command.exec(language="JAVASCRIPT", code=code) + if output.exit_code > 0: + raise ToolException( + f"Riza code execution returned a non-zero exit code. " + f"The output captured from stderr was:\n{output.stderr}" + ) + return output.stdout