diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml index 0133cb3e6..c5baf4d42 100644 --- a/.github/workflows/codespell.yml +++ b/.github/workflows/codespell.yml @@ -36,7 +36,7 @@ - name: Codespell uses: codespell-project/actions-codespell@v2 with: - skip: '*.ambr,*.lock,*.ipynb,*.yaml,*.zlib' + skip: '*.ambr,*.lock,*.ipynb,*.yaml,*.zlib,*.md' ignore_words_list: ${{ steps.extract_ignore_words.outputs.ignore_words_list }} # We do this to avoid spellchecking cell outputs - name: Codespell Notebooks diff --git a/.github/workflows/deploy_docs.yml b/.github/workflows/deploy_docs.yml index cea5ce386..6548623b5 100644 --- a/.github/workflows/deploy_docs.yml +++ b/.github/workflows/deploy_docs.yml @@ -48,7 +48,7 @@ jobs: deploy: # needs: run-changed-notebooks runs-on: ubuntu-latest - timeout-minutes: 10 # Job will be cancelled if it runs for more than 10 minutes + timeout-minutes: 10 # Job will be cancelled if it runs for more than 10 minutes env: GITHUB_TOKEN: ${{ secrets.MKDOCS_GITHUB_TOKEN }} steps: @@ -63,17 +63,29 @@ jobs: poetry-version: ${{ env.POETRY_VERSION }} cache-key: docs + - name: Use Node.js + uses: actions/setup-node@v3 + with: + node-version: "22" + cache: "yarn" + cache-dependency-path: docs/yarn.lock + - name: Install dependencies run: | - poetry install --with test --no-root + yarn + poetry install --with test --with docs --no-root poetry run pip install -U \ pytest \ pytest-check-links \ - langsmith \ - langchain \ GitPython \ "git+https://${GITHUB_TOKEN}@github.com/langchain-ai/mkdocs-material-insiders.git" \ - "git+https://github.com/benjamincburns/markdown-exec.git@10cdd338bfdb1f99705b3a4d06b244f7f185ecae" + "git+https://github.com/benjamincburns/markdown-exec.git@cc0d39d737e5ffd4b83d23cd8729d7ea16e363c8" + + poetry run jupyter kernelspec list + poetry run python3 -m ipykernel install --user --name=python3 + npm install -g tslab + poetry run tslab install --python=python3 + poetry run jupyter kernelspec list - name: Lint Docs # This step lints the docs using the existing linting set up. @@ -85,6 +97,8 @@ jobs: run: make build-docs env: MKDOCS_GIT_COMMITTERS_APIKEY: ${{ secrets.MKDOCS_GIT_COMMITTERS_APIKEY }} + OPENAI_API_KEY: sf-proj-1234567890 # fake placeholder, shouldn't actually be used + ANTHROPIC_API_KEY: sk-ant-api03-1234567890 # fake placeholder, shouldn't actually be used - name: Check links in notebooks env: LANGCHAIN_API_KEY: test @@ -135,7 +149,7 @@ jobs: uses: actions/configure-pages@v4 - name: Upload Pages Artifact - if: github.ref == 'refs/heads/main' + # if: github.ref == 'refs/heads/main' uses: actions/upload-pages-artifact@v3 with: path: ./docs/site/ diff --git a/docs/.gitignore b/docs/.gitignore index 05eab379e..f4d716881 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -2,4 +2,3 @@ site/ docs/cloud/reference/sdk/js_ts_sdk_ref.md .vercel -cassettes/ diff --git a/docs/Makefile b/docs/Makefile index 6308401f6..c599591e7 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -20,12 +20,20 @@ llms-text: poetry run python _scripts/generate_llms_text.py docs/llms-full.txt install-vercel-deps: + dnf install -y python3.11 curl -sSL https://install.python-poetry.org | python3 - poetry self update 1.8.5 + # don't use vercel's python - it wasn't compiled with sqlite support, and it fails when installing ipython's kernel + poetry env use /usr/bin/python3.11 + poetry install --with docs --with test --no-root + poetry run pip install "git+https://github.com/benjamincburns/markdown-exec.git@cc0d39d737e5ffd4b83d23cd8729d7ea16e363c8" + poetry run python3 -m ipykernel install --name=python3 + npm install -g tslab + poetry run tslab install --python=python3 + poetry run jupyter kernelspec list + vercel-build-docs: install-vercel-deps - poetry install - poetry run pip install "git+https://github.com/benjamincburns/markdown-exec.git@26c64551340da6ffcc8cb4f53db99e8c239d9919" make build-docs diff --git a/docs/_scripts/assets/vcr_setup_preamble.py b/docs/_scripts/assets/vcr_setup_preamble.py index e92045f8f..efa9c7109 100644 --- a/docs/_scripts/assets/vcr_setup_preamble.py +++ b/docs/_scripts/assets/vcr_setup_preamble.py @@ -1,15 +1,12 @@ import base64 import os import zlib -from logging import getLogger from types import TracebackType from typing import Optional, Any, Type import msgpack import vcr -logger = getLogger(__name__) - os.environ.pop("LANGCHAIN_TRACING_V2", None) custom_vcr = vcr.VCR() @@ -54,8 +51,10 @@ class HashedCassette: self.hash_value: str = hash_value self.vcr: vcr.VCR = custom_vcr self.cassette_context: Optional[Any] = None + self.exited: bool = False def __enter__(self) -> Any: + self.exited: bool = False # Get the serializer instance from the VCR instance. serializer = self.vcr.serializers[self.vcr.serializer] # If the cassette file exists, check its embedded hash. @@ -65,12 +64,10 @@ class HashedCassette: try: cassette_data = serializer.deserialize(content) except Exception as e: - print(f"Error deserializing cassette, removing file: {e}") os.remove(self.cassette_path) else: existing_hash = cassette_data.get("cassette_hash") if existing_hash != self.hash_value: - print("Hash mismatch. Removing outdated cassette.") os.remove(self.cassette_path) # Now enter the VCR cassette context. self.cassette_context = custom_vcr.use_cassette( @@ -87,6 +84,9 @@ class HashedCassette: exc_val: Optional[BaseException] = None, exc_tb: Optional[TracebackType] = None, ) -> Optional[bool]: + if self.exited: + return + self.exited = True # Exit the VCR cassette context. result = self.cassette_context.__exit__(exc_type, exc_val, exc_tb) serializer = self.vcr.serializers[self.vcr.serializer] @@ -97,7 +97,6 @@ class HashedCassette: try: cassette_data = serializer.deserialize(content) except Exception as e: - logger.error(f"Error deserializing cassette during exit: {e}") return result # Update the cassette data with the expected hash. if cassette_data.get("cassette_hash") != self.hash_value: diff --git a/docs/_scripts/notebook_convert.py b/docs/_scripts/notebook_convert.py index 8a47c44cc..d897fd397 100644 --- a/docs/_scripts/notebook_convert.py +++ b/docs/_scripts/notebook_convert.py @@ -1,6 +1,8 @@ +import argparse import os import re from pathlib import Path +from typing import Literal, Optional import nbformat from nbconvert.exporters import MarkdownExporter @@ -8,23 +10,45 @@ from nbconvert.preprocessors import Preprocessor class EscapePreprocessor(Preprocessor): + def __init__(self, rewrite_links: bool = True, **kwargs) -> None: + super().__init__(**kwargs) + self.rewrite_links = rewrite_links + def preprocess_cell(self, cell, resources, cell_index): if cell.cell_type == "markdown": - # rewrite markdown links to html links (excluding image links) - cell.source = re.sub( - r"(?\1', - cell.source, - ) + if self.rewrite_links: + # We'll need to adjust the logic for this to keep markdown format + # but link to markdown files rather than ipynb files. + cell.source = re.sub( + r"(?\1', + cell.source, + ) + else: + # Keep format but replace the .ipynb extension with .md + cell.source = re.sub( + r"(? tags cell.source = re.sub( r' Path: + mode: Literal["markdown", "exec"] = "markdown", +) -> str: with open(notebook_path) as f: nb = nbformat.read(f, as_version=4) - body, _ = exporter.from_notebook_node(nb) + nb.metadata.mode = mode + if mode == "markdown": + body, _ = exporter.from_notebook_node(nb) + else: + body, _ = md_executable.from_notebook_node(nb) return body + + +HERE = Path(__file__).parent +DOCS = HERE.parent / "docs" + + +# Convert notebooks to markdown +def _convert_notebooks( + *, + output_dir: Optional[Path] = None, + replace: bool = False, + pattern: str = "*.ipynb", +) -> None: + """Converting notebooks.""" + if not output_dir and not replace: + raise ValueError("Either --output_dir or --replace must be specified") + + output_dir_path = DOCS if replace else Path(output_dir) + notebooks = list(DOCS.rglob(pattern)) + + file_names = [notebook.name for notebook in notebooks] + + for notebook in notebooks: + markdown = convert_notebook(notebook, mode="exec") + markdown_path = output_dir_path / notebook.relative_to(DOCS).with_suffix(".md") + markdown_path.parent.mkdir(parents=True, exist_ok=True) + with open(markdown_path, "w") as f: + f.write(markdown) + if replace: + notebook.unlink(missing_ok=False) + + if replace: + # The regex will match markdown links that point to *.ipynb files. + # It captures: + # group(1): the link text (inside the square brackets) + # group(2): the file path (without the trailing .ipynb) + link_pattern = r"(? str: + link_text = match.group(1) + link_target = match.group(2) + # Reconstruct the file name with the .ipynb extension. + # For example, if link_target is "foo/bar", then linked_file becomes "bar.ipynb". + linked_file = Path(link_target).name + ".ipynb" + # Only update if the notebook was among those converted. + if linked_file in file_names: + # Change the extension from .ipynb to .md + return f"[{link_text}]({link_target}.md)" + # Otherwise, leave the original link intact. + return match.group(0) + + # Process all markdown files in the output directory. + for path in output_dir_path.rglob("*.md"): + with open(path, "r", encoding="utf-8") as f: + content = f.read() + new_content = re.sub(link_pattern, replace_link, content) + with open(path, "w", encoding="utf-8") as f: + f.write(new_content) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Convert notebooks to markdown") + parser.add_argument( + "--output_dir", + default=None, + help="Directory to output markdown files", + ) + parser.add_argument( + "--replace", + action="store_true", + help="Replace original notebooks with markdown files", + ) + parser.add_argument( + "--pattern", + default="*.ipynb", + help="Glob pattern to match notebooks to convert", + ) + args = parser.parse_args() + _convert_notebooks( + replace=args.replace, + output_dir=args.output_dir, + pattern=args.pattern, + ) diff --git a/docs/_scripts/notebook_convert_templates/md_executable/conf.json b/docs/_scripts/notebook_convert_templates/md_executable/conf.json new file mode 100644 index 000000000..7adab7c92 --- /dev/null +++ b/docs/_scripts/notebook_convert_templates/md_executable/conf.json @@ -0,0 +1,5 @@ +{ + "mimetypes": { + "text/markdown": true + } +} \ No newline at end of file diff --git a/docs/_scripts/notebook_convert_templates/md_executable/index.md.j2 b/docs/_scripts/notebook_convert_templates/md_executable/index.md.j2 new file mode 100644 index 000000000..e784b6b07 --- /dev/null +++ b/docs/_scripts/notebook_convert_templates/md_executable/index.md.j2 @@ -0,0 +1,36 @@ +{#https://github.com/rdbisme/nbconvert/blob/master/share/jupyter/nbconvert/templates/markdown/index.md.j2#} +{% extends 'markdown/index.md.j2' %} + +{% block input %} +``` +{%- if 'magics_language' in cell.metadata -%} + {{ cell.metadata.magics_language}} +{%- elif 'name' in nb.metadata.get('language_info', {}) -%} + {{ nb.metadata.language_info.name }} exec="on" source="above" session="1" +{%- endif %} +{{ cell.source}} +``` +{% endblock input %} + +{%- block traceback_line -%} +{%- endblock traceback_line -%} + +{%- block stream -%} +{%- endblock stream -%} + +{%- block data_text scoped -%} +{%- endblock data_text -%} + +{%- block data_html scoped -%} +```html +{{ output.data['text/html'] | safe }} +``` +{%- endblock data_html -%} + +{%- block data_jpg scoped -%} +![](data:image/jpg;base64,{{ output.data['image/jpeg'] }}) +{%- endblock data_jpg -%} + +{%- block data_png scoped -%} +![](data:image/png;base64,{{ output.data['image/png'] }}) +{%- endblock data_png -%} diff --git a/docs/_scripts/notebook_hooks.py b/docs/_scripts/notebook_hooks.py index 4af9f47bb..e5d9dec8e 100644 --- a/docs/_scripts/notebook_hooks.py +++ b/docs/_scripts/notebook_hooks.py @@ -16,6 +16,7 @@ from generate_api_reference_links import update_markdown_with_imports from notebook_convert import convert_notebook from setup_vcr import load_postamble, load_preamble, _hash_string + logger = logging.getLogger(__name__) logging.basicConfig() logger.setLevel(logging.INFO) @@ -163,26 +164,27 @@ def handle_vcr_setup( id: str, md: Markdown, **kwargs: Dict[str, Any], -) -> str: +) -> Dict[str, Any]: """Handle VCR setup in markdown content if necessary.""" try: if kwargs.get("extra", None) is None: - raise ValueError( + raise SuperFencesException( f"error while processing {language} block: extra dict is required" ) if kwargs["extra"].get("path", None) is None: - raise ValueError( + raise SuperFencesException( f"error while processing {language} block: path is required" ) document_filename = kwargs["extra"]["path"] - logger.info("document_filename: %s", document_filename) - if session is None or session == "" and id is None or id == "": id = _hash_string(code) + if session is not None and session != "": + logger.info(f"new session {session} on page {document_filename}") + cassette_prefix = document_filename.replace(".md", "").replace(os.path.sep, "_") cassette_dir = os.path.abspath( @@ -204,6 +206,9 @@ def handle_vcr_setup( ] if session is None or session == "": + logger.info( + f"no session, adding postamble for {language} in {document_filename}" + ) wrapped_lines.append(load_postamble(language)) transformed_source = "\n".join(wrapped_lines) @@ -223,20 +228,34 @@ def handle_vcr_teardown( session: str, history: list[SessionHistoryEntry], ): - session = history[-1].inputs["session"] - inputs = dict(history[-1].inputs) - del inputs["session"] - del inputs["code"] - del inputs["language"] - del inputs["id"] - formatter( - code="_cassette.__exit__() # markdown-exec: hide", - language="python", + last_inputs = dict(history[-1].inputs) + code = load_postamble(language) + md = last_inputs["md"] + html = False + update_toc = False + + document_filename = last_inputs.get("extra", {}).get("path", None) + + if document_filename is None: + logger.warning(f"no document filename found while tearing down {session}!") + else: + logger.info(f"tearing down {session} on {document_filename}") + logger.info(traceback.format_stack()) + + kwargs = dict( + code=code, session=session, id=f"{id}_vcr_end", - **inputs, + md=md, + html=html, + update_toc=update_toc, + extra={}, ) + # This doesn't actually render anything, we just call the formatter so it + # executes in the same context as the session of which we're disposing. + formatter(**kwargs) + def _on_page_markdown_with_config( markdown: str, @@ -250,7 +269,7 @@ def _on_page_markdown_with_config( return markdown if page.file.src_path.endswith(".ipynb"): - logger.info("Processing Jupyter notebook: %s", page.file.src_path) + # logger.info("Processing Jupyter notebook: %s", page.file.src_path) markdown = convert_notebook(page.file.abs_src_path) # Append API reference links to code blocks @@ -266,7 +285,7 @@ def _on_page_markdown_with_config( if remove_base64_images: # Remove base64 encoded images from markdown - markdown = re.sub(r"!\[.*?\]\(data:image/[^;]+;base64,[^\)]+\)", "", markdown) + markdown = re.sub(r"!\[.*?\]\(data:image/+;base64,[^\)]+\)", "", markdown) return markdown diff --git a/docs/_scripts/setup_vcr.py b/docs/_scripts/setup_vcr.py index 9bcdfbdb7..efd0283a3 100644 --- a/docs/_scripts/setup_vcr.py +++ b/docs/_scripts/setup_vcr.py @@ -37,12 +37,16 @@ def _get_typescript_cassette_cleanup() -> str: preamble_inits = { "python": _get_python_cassette_init, + "py": _get_python_cassette_init, "typescript": _get_typescript_cassette_init, + "ts": _get_typescript_cassette_init, } preamble_cleanups = { "python": _get_python_cassette_cleanup, + "py": _get_python_cassette_cleanup, "typescript": _get_typescript_cassette_cleanup, + "ts": _get_typescript_cassette_cleanup, } diff --git a/docs/cassettes/how-tos_create-react-agent_1_python.msgpack.zlib b/docs/cassettes/how-tos_create-react-agent_1_python.msgpack.zlib new file mode 100644 index 000000000..19c0d41f5 --- /dev/null +++ b/docs/cassettes/how-tos_create-react-agent_1_python.msgpack.zlib @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/docs/codespell_notebooks.sh b/docs/codespell_notebooks.sh index e58c4be78..98d4afe60 100755 --- a/docs/codespell_notebooks.sh +++ b/docs/codespell_notebooks.sh @@ -1,6 +1,17 @@ ERROR_FOUND=0 for file in $(find $1 -name "*.ipynb" | grep -v ".ipynb_checkpoints"); do - OUTPUT=$(cat "$file" | jupytext --from ipynb --to py:percent | codespell -) + # Adding regexp to ignore base64 strings + OUTPUT=$(cat "$file" | jupytext --from ipynb --to py:percent | codespell --ignore-regex='[A-Za-z0-9+/=]{25,}' -) + if [ -n "$OUTPUT" ]; then + echo "Errors found in $file" + echo "$OUTPUT" + ERROR_FOUND=1 + fi +done + +for file in $(find $1 -name "*.md"); do + # Adding regexp to ignore base64 strings + OUTPUT=$(cat "$file" | codespell --ignore-regex='[A-Za-z0-9+/=]{25,}' -) if [ -n "$OUTPUT" ]; then echo "Errors found in $file" echo "$OUTPUT" diff --git a/docs/docs/how-tos/create-react-agent.ipynb b/docs/docs/how-tos/create-react-agent.ipynb deleted file mode 100644 index 90d2875cb..000000000 --- a/docs/docs/how-tos/create-react-agent.ipynb +++ /dev/null @@ -1,300 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "992c4695-ec4f-428d-bd05-fb3b5fbd70f4", - "metadata": {}, - "source": [ - "# How to use the pre-built ReAct agent" - ] - }, - { - "cell_type": "markdown", - "id": "e0fcced0-9767-412f-90f9-7f3cd618ff90", - "metadata": {}, - "source": [ - "
\n", - "

Prerequisites

\n", - "

\n", - " This guide assumes familiarity with the following:\n", - "

\n", - "

\n", - "
\n", - "\n", - "In this how-to we'll create a simple [ReAct](https://arxiv.org/abs/2210.03629) agent app that can check the weather. The app consists of an agent (LLM) and tools. As we interact with the app, we will first call the agent (LLM) to decide if we should use tools. Then we will run a loop: \n", - "\n", - "1. If the agent said to take an action (i.e. call tool), we'll run the tools and pass the results back to the agent\n", - "2. If the agent did not ask to run tools, we will finish (respond to the user)\n", - "\n", - "
\n", - "

Prebuilt Agent

\n", - "

\n", - "Please note that here will we use a prebuilt agent. One of the big benefits of LangGraph is that you can easily create your own agent architectures. So while it's fine to start here to build an agent quickly, we would strongly recommend learning how to build your own agent so that you can take full advantage of LangGraph.\n", - "

\n", - "
" - ] - }, - { - "cell_type": "markdown", - "id": "7be3889f-3c17-4fa1-bd2b-84114a2c7247", - "metadata": {}, - "source": [ - "## Setup\n", - "\n", - "First let's install the required packages and set our API keys" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "a213e11a-5c62-4ddb-a707-490d91add383", - "metadata": {}, - "outputs": [], - "source": [ - "%%capture --no-stderr\n", - "%pip install -U langgraph langchain-openai" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "23a1885c-04ab-4750-aefa-105891fddf3e", - "metadata": {}, - "outputs": [], - "source": [ - "import getpass\n", - "import os\n", - "\n", - "\n", - "def _set_env(var: str):\n", - " if not os.environ.get(var):\n", - " os.environ[var] = getpass.getpass(f\"{var}: \")\n", - "\n", - "\n", - "_set_env(\"OPENAI_API_KEY\")" - ] - }, - { - "cell_type": "markdown", - "id": "035b920d", - "metadata": {}, - "source": [ - "
\n", - "

Set up LangSmith for LangGraph development

\n", - "

\n", - " Sign up for LangSmith to quickly spot issues and improve the performance of your LangGraph projects. LangSmith lets you use trace data to debug, test, and monitor your LLM apps built with LangGraph — read more about how to get started here. \n", - "

\n", - "
" - ] - }, - { - "cell_type": "markdown", - "id": "03c0f089-070c-4cd4-87e0-6c51f2477b82", - "metadata": {}, - "source": [ - "## Code" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "7a154152-973e-4b5d-aa13-48c617744a4c", - "metadata": {}, - "outputs": [], - "source": [ - "# First we initialize the model we want to use.\n", - "from langchain_openai import ChatOpenAI\n", - "\n", - "model = ChatOpenAI(model=\"gpt-4o\", temperature=0)\n", - "\n", - "\n", - "# For this tutorial we will use custom tool that returns pre-defined values for weather in two cities (NYC & SF)\n", - "\n", - "from typing import Literal\n", - "\n", - "from langchain_core.tools import tool\n", - "\n", - "\n", - "@tool\n", - "def get_weather(city: Literal[\"nyc\", \"sf\"]):\n", - " \"\"\"Use this to get weather information.\"\"\"\n", - " if city == \"nyc\":\n", - " return \"It might be cloudy in nyc\"\n", - " elif city == \"sf\":\n", - " return \"It's always sunny in sf\"\n", - " else:\n", - " raise AssertionError(\"Unknown city\")\n", - "\n", - "\n", - "tools = [get_weather]\n", - "\n", - "\n", - "# Define the graph\n", - "\n", - "from langgraph.prebuilt import create_react_agent\n", - "\n", - "graph = create_react_agent(model, tools=tools)" - ] - }, - { - "cell_type": "markdown", - "id": "00407425-506d-4ffd-9c86-987921d8c844", - "metadata": {}, - "source": [ - "## Usage\n", - "\n", - "First, let's visualize the graph we just created" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "fa16de4c-aac0-4ff4-ab69-60d399f75423", - "metadata": {}, - "outputs": [ - { - "data": { - "image/jpeg": "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", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "from IPython.display import Image, display\n", - "\n", - "display(Image(graph.get_graph().draw_mermaid_png()))" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "16636975-5f2d-4dc7-ab8e-d0bea0830a28", - "metadata": {}, - "outputs": [], - "source": [ - "def print_stream(stream):\n", - " for s in stream:\n", - " message = s[\"messages\"][-1]\n", - " if isinstance(message, tuple):\n", - " print(message)\n", - " else:\n", - " message.pretty_print()" - ] - }, - { - "cell_type": "markdown", - "id": "9d187d6b-0fb6-4860-8771-160c3cf403c6", - "metadata": {}, - "source": [ - "Let's run the app with an input that needs a tool call" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "9ffff6c3-a4f5-47c9-b51d-97caaee85cd6", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "================================\u001b[1m Human Message \u001b[0m=================================\n", - "\n", - "what is the weather in sf\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "Tool Calls:\n", - " get_weather (call_zVvnU9DKr6jsNnluFIl59mHb)\n", - " Call ID: call_zVvnU9DKr6jsNnluFIl59mHb\n", - " Args:\n", - " city: sf\n", - "=================================\u001b[1m Tool Message \u001b[0m=================================\n", - "Name: get_weather\n", - "\n", - "It's always sunny in sf\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "\n", - "The weather in San Francisco is currently sunny.\n" - ] - } - ], - "source": [ - "inputs = {\"messages\": [(\"user\", \"what is the weather in sf\")]}\n", - "print_stream(graph.stream(inputs, stream_mode=\"values\"))" - ] - }, - { - "cell_type": "markdown", - "id": "838a043f-90ad-4e69-9d1d-6e22db2c346c", - "metadata": {}, - "source": [ - "Now let's try a question that doesn't need tools" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "187479f9-32fa-4611-9487-cf816ba2e147", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "================================\u001b[1m Human Message \u001b[0m=================================\n", - "\n", - "who built you?\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "\n", - "I was created by OpenAI, a research organization focused on developing and advancing artificial intelligence technology.\n" - ] - } - ], - "source": [ - "inputs = {\"messages\": [(\"user\", \"who built you?\")]}\n", - "print_stream(graph.stream(inputs, stream_mode=\"values\"))" - ] - } - ], - "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/docs/docs/how-tos/create-react-agent.md b/docs/docs/how-tos/create-react-agent.md new file mode 100644 index 000000000..663f5f6fa --- /dev/null +++ b/docs/docs/how-tos/create-react-agent.md @@ -0,0 +1,146 @@ +# How to use the pre-built ReAct agent + +
+

Prerequisites

+

+ This guide assumes familiarity with the following: +

+

+
+ +In this how-to we'll create a simple [ReAct](https://arxiv.org/abs/2210.03629) agent app that can check the weather. The app consists of an agent (LLM) and tools. As we interact with the app, we will first call the agent (LLM) to decide if we should use tools. Then we will run a loop: + +1. If the agent said to take an action (i.e. call tool), we'll run the tools and pass the results back to the agent +2. If the agent did not ask to run tools, we will finish (respond to the user) + +
+

Prebuilt Agent

+

+Please note that here will we use a prebuilt agent. One of the big benefits of LangGraph is that you can easily create your own agent architectures. So while it's fine to start here to build an agent quickly, we would strongly recommend learning how to build your own agent so that you can take full advantage of LangGraph. +

+
+ +## Setup + +First let's install the required packages and set our API keys + + +```python +%%capture --no-stderr +%pip install -U langgraph langchain-openai +``` + + +```python exec="on" source="above" session="1" +import getpass +import os + + +def _set_env(var: str): + if not os.environ.get(var): + os.environ[var] = getpass.getpass(f"{var}: ") + + +_set_env("OPENAI_API_KEY") +``` + +
+

Set up LangSmith for LangGraph development

+

+ Sign up for LangSmith to quickly spot issues and improve the performance of your LangGraph projects. LangSmith lets you use trace data to debug, test, and monitor your LLM apps built with LangGraph — read more about how to get started here. +

+
+ +## Code + + +```python exec="on" source="above" session="1" +# First we initialize the model we want to use. +from langchain_openai import ChatOpenAI + +model = ChatOpenAI(model="gpt-4o", temperature=0) + + +# For this tutorial we will use custom tool that returns pre-defined values for weather in two cities (NYC & SF) + +from typing import Literal + +from langchain_core.tools import tool + + +@tool +def get_weather(city: Literal["nyc", "sf"]): + """Use this to get weather information.""" + if city == "nyc": + return "It might be cloudy in nyc" + elif city == "sf": + return "It's always sunny in sf" + else: + raise AssertionError("Unknown city") + + +tools = [get_weather] + + +# Define the graph + +from langgraph.prebuilt import create_react_agent + +graph = create_react_agent(model, tools=tools) +``` + +## Usage + +First, let's visualize the graph we just created + + +```python exec="on" source="above" session="1" +from IPython.display import Image, display + +display(Image(graph.get_graph().draw_mermaid_png())) +``` + +![](data:image/jpg;base64,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) + + +```python exec="on" source="above" session="1" +def print_stream(stream): + for s in stream: + message = s["messages"][-1] + if isinstance(message, tuple): + print(message) + else: + message.pretty_print() +``` + +Let's run the app with an input that needs a tool call + + +```python exec="on" source="above" session="1" result="ansi" +inputs = {"messages": [("user", "what is the weather in sf")]} +print_stream(graph.stream(inputs, stream_mode="values")) +``` + +Now let's try a question that doesn't need tools + + +```python exec="on" source="above" session="1" result="ansi" +inputs = {"messages": [("user", "who built you?")]} +print_stream(graph.stream(inputs, stream_mode="values")) +``` diff --git a/docs/docs/how-tos/index.md b/docs/docs/how-tos/index.md index f5218f87d..03dd84012 100644 --- a/docs/docs/how-tos/index.md +++ b/docs/docs/how-tos/index.md @@ -162,7 +162,7 @@ One of the big benefits of LangGraph is that you can easily create your own agen These guides show how to use the prebuilt ReAct agent: -- [How to use the pre-built ReAct agent](create-react-agent.ipynb) +- [How to use the pre-built ReAct agent](create-react-agent.md) - [How to add thread-level memory to a ReAct Agent](create-react-agent-memory.ipynb) - [How to add a custom system prompt to a ReAct agent](create-react-agent-system-prompt.ipynb) - [How to add human-in-the-loop processes to a ReAct agent](create-react-agent-hitl.ipynb) diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index b06b2b0f2..cf945b3d3 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -203,7 +203,7 @@ nav: - how-tos/autogen-integration-functional.ipynb - Prebuilt ReAct Agent: - Prebuilt ReAct Agent: how-tos#prebuilt-react-agent - - how-tos/create-react-agent.ipynb + - how-tos/create-react-agent.md - how-tos/create-react-agent-memory.ipynb - how-tos/create-react-agent-system-prompt.ipynb - how-tos/create-react-agent-hitl.ipynb diff --git a/docs/package.json b/docs/package.json index 46a9a6533..1a5908a84 100644 --- a/docs/package.json +++ b/docs/package.json @@ -3,7 +3,7 @@ "version": "1.0.0", "license": "MIT", "scripts": { - "build": "echo 'export PATH=$PATH:/vercel/.local/bin:$PATH' > ~/.bashrc && source ~/.bashrc && make vercel-build-docs" + "build": "echo 'export OPENAI_API_KEY=\"sk-proj-1234567890\"' >> ~/.bashrc && echo 'export ANTHROPIC_API_KEY=\"sk-ant-api03-1234567890\"' >> ~/.bashrc && echo 'export PATH=$PATH:/vercel/.local/bin:$PATH' >> ~/.bashrc && source ~/.bashrc && make vercel-build-docs" }, "dependencies": { "@langchain/core": "^0.3.38",