Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
52910f3b04 |
@@ -7,29 +7,35 @@ body:
|
||||
value: >
|
||||
Thank you for taking the time to file a bug report.
|
||||
|
||||
Use this to report BUGS in LangGraph. For usage questions, feature requests and general design questions, please use [GitHub Discussions](https://github.com/langchain-ai/langgraph/discussions).
|
||||
Use this to report bugs in LangChain.
|
||||
|
||||
If you're not certain that your issue is due to a bug in LangChain, please use [GitHub Discussions](https://github.com/langchain-ai/langchain/discussions)
|
||||
to ask for help with your issue.
|
||||
|
||||
Relevant links to check before filing a bug report to see if your issue has already been reported, fixed or
|
||||
if there's another way to solve your problem:
|
||||
|
||||
[LangGraph Github Discussions](https://github.com/langchain-ai/langgraph/discussions),
|
||||
[LangGraph Github Issues](https://github.com/langchain-ai/langgraph/issues),
|
||||
[LangGraph how-to guides](https://langchain-ai.github.io/langgraph/how-tos/).
|
||||
[LangGraph documentation](https://langchain-ai.github.io/langgraph/).
|
||||
[LangChain documentation with the integrated search](https://python.langchain.com/docs/get_started/introduction),
|
||||
[GitHub search](https://github.com/langchain-ai/langgraph),
|
||||
[LangChain Github Discussions](https://github.com/langchain-ai/langgraph/discussions),
|
||||
[LangChain Github Issues](https://github.com/langchain-ai/langgraph/issues),
|
||||
[LangChain ChatBot](https://chat.langchain.com/)
|
||||
- type: checkboxes
|
||||
id: checks
|
||||
attributes:
|
||||
label: Checked other resources
|
||||
description: Before submitting this issue, please confirm that you have completed all the steps below by checking each option. These steps help ensure your issue is well-defined, relevant, and actionable.
|
||||
description: Please confirm and check all the following options.
|
||||
options:
|
||||
- label: This is a bug, not a usage question. For questions, please use GitHub Discussions.
|
||||
- label: I added a very descriptive title to this issue.
|
||||
required: true
|
||||
- label: I added a clear and detailed title that summarizes the issue.
|
||||
- label: I searched the [LangGraph](https://langchain-ai.github.io/langgraph/)/LangChain documentation with the integrated search.
|
||||
required: true
|
||||
- label: I read what a minimal reproducible example is (https://stackoverflow.com/help/minimal-reproducible-example).
|
||||
- label: I used the GitHub search to find a similar question and didn't find it.
|
||||
required: true
|
||||
- label: I included a self-contained, minimal example that demonstrates the issue INCLUDING all the relevant imports. The code run AS IS to reproduce the issue.
|
||||
- label: I am sure that this is a bug in LangGraph/LangChain rather than my code.
|
||||
required: true
|
||||
- label: I am sure this is better as an issue [rather than a GitHub discussion](https://github.com/langchain-ai/langgraph/discussions/new/choose), since this is a LangGraph bug and not a design question.
|
||||
required: true
|
||||
- type: textarea
|
||||
id: reproduction
|
||||
@@ -39,6 +45,14 @@ body:
|
||||
label: Example Code
|
||||
description: |
|
||||
Please add a self-contained, [minimal, reproducible, example](https://stackoverflow.com/help/minimal-reproducible-example) with your use case.
|
||||
|
||||
If a maintainer can copy it, run it, and see it right away, there's a much higher chance that you'll be able to get help.
|
||||
|
||||
**Important!**
|
||||
|
||||
* Reduce your code to the minimum required to reproduce the issue if possible. This makes it much easier for others to help you.
|
||||
* Avoid screenshots when possible, as they are hard to read and (more importantly) don't allow others to copy-and-paste your code.
|
||||
|
||||
placeholder: |
|
||||
from langgraph.graph import StateGraph
|
||||
|
||||
@@ -78,8 +92,25 @@ body:
|
||||
attributes:
|
||||
label: System Info
|
||||
description: |
|
||||
Please share your system info with us.
|
||||
|
||||
"pip freeze | grep langchain"
|
||||
platform (windows / linux / mac)
|
||||
python version
|
||||
|
||||
OR if you're on a recent version of langchain-core you can paste the output of:
|
||||
|
||||
python -m langchain_core.sys_info
|
||||
placeholder: |
|
||||
"pip freeze | grep langgraph"
|
||||
platform
|
||||
python version
|
||||
|
||||
Alternatively, if you're on a recent version of langchain-core you can paste the output of:
|
||||
|
||||
python -m langchain_core.sys_info
|
||||
|
||||
These will only surface LangChain packages, don't forget to include any other relevant
|
||||
packages you're using (if you're not sure what's relevant, you can paste the entire output of `pip freeze`).
|
||||
validations:
|
||||
required: true
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
import asyncio
|
||||
import json
|
||||
import os
|
||||
import pathlib
|
||||
import sys
|
||||
import langgraph_cli
|
||||
import langgraph_cli.docker
|
||||
import langgraph_cli.config
|
||||
|
||||
from langgraph_cli.exec import Runner, subp_exec
|
||||
from langgraph_cli.progress import Progress
|
||||
from langgraph_cli.constants import DEFAULT_PORT
|
||||
|
||||
|
||||
def test(
|
||||
config: pathlib.Path,
|
||||
port: int,
|
||||
tag: str,
|
||||
verbose: bool,
|
||||
):
|
||||
with Runner() as runner, Progress(message="Pulling...") as set:
|
||||
# check docker available
|
||||
capabilities = langgraph_cli.docker.check_capabilities(runner)
|
||||
# open config
|
||||
config_json = langgraph_cli.config.validate_config_file(config)
|
||||
|
||||
set("Running...")
|
||||
args = [
|
||||
"run",
|
||||
"--rm",
|
||||
"-p",
|
||||
f"{port}:8000",
|
||||
]
|
||||
if isinstance(config_json["env"], str):
|
||||
args.extend(
|
||||
[
|
||||
"--env-file",
|
||||
str(config.parent / config_json["env"]),
|
||||
]
|
||||
)
|
||||
else:
|
||||
for k, v in config_json["env"].items():
|
||||
args.extend(
|
||||
[
|
||||
"-e",
|
||||
f"{k}={v}",
|
||||
]
|
||||
)
|
||||
if capabilities.healthcheck_start_interval:
|
||||
args.extend(
|
||||
[
|
||||
"--health-interval",
|
||||
"5s",
|
||||
"--health-retries",
|
||||
"1",
|
||||
"--health-start-period",
|
||||
"10s",
|
||||
"--health-start-interval",
|
||||
"1s",
|
||||
]
|
||||
)
|
||||
else:
|
||||
args.extend(
|
||||
[
|
||||
"--health-interval",
|
||||
"5s",
|
||||
"--health-retries",
|
||||
"2",
|
||||
]
|
||||
)
|
||||
|
||||
_task = None
|
||||
|
||||
def on_stdout(line: str):
|
||||
nonlocal _task
|
||||
if "GET /ok" in line or "Uvicorn running on" in line:
|
||||
set("")
|
||||
sys.stdout.write(
|
||||
f"""Ready!
|
||||
- API: http://localhost:{port}
|
||||
"""
|
||||
)
|
||||
sys.stdout.flush()
|
||||
_task.cancel()
|
||||
return True
|
||||
return False
|
||||
|
||||
async def subp_exec_task(*args, **kwargs):
|
||||
nonlocal _task
|
||||
_task = asyncio.create_task(subp_exec(*args, **kwargs))
|
||||
await _task
|
||||
|
||||
try:
|
||||
runner.run(
|
||||
subp_exec_task(
|
||||
"docker",
|
||||
*args,
|
||||
tag,
|
||||
verbose=verbose,
|
||||
on_stdout=on_stdout,
|
||||
)
|
||||
)
|
||||
except asyncio.CancelledError:
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("-t", "--tag", type=str)
|
||||
parser.add_argument("-c", "--config", type=str, default="./langgraph.json")
|
||||
parser.add_argument("-p", "--port", default=DEFAULT_PORT)
|
||||
args = parser.parse_args()
|
||||
test(pathlib.Path(args.config), args.port, args.tag, verbose=True)
|
||||
@@ -39,36 +39,22 @@ jobs:
|
||||
- name: Install cli globally
|
||||
if: steps.changed-files.outputs.all
|
||||
run: pip install -e .
|
||||
- name: Build and test service A
|
||||
- name: Start service A
|
||||
if: steps.changed-files.outputs.all
|
||||
working-directory: libs/cli/examples
|
||||
run: |
|
||||
# The build-arg isn't used; just testing that we accept other args
|
||||
langgraph build -t langgraph-test-a --base-image "langchain/langgraph-trial"
|
||||
cp .env.example .envg
|
||||
timeout 60 python ../../../.github/scripts/run_langgraph_cli_test.py -c langgraph.json -t langgraph-test-a
|
||||
- name: Build and test service B
|
||||
timeout 60 langgraph test -c examples/langgraph.json --verbose || (exit "$(($? == 124 ? 0 : $?))")
|
||||
- name: Start service B
|
||||
if: steps.changed-files.outputs.all
|
||||
working-directory: libs/cli/examples/graphs
|
||||
run: |
|
||||
langgraph build -t langgraph-test-b --base-image "langchain/langgraph-trial"
|
||||
timeout 60 python ../../../../.github/scripts/run_langgraph_cli_test.py -t langgraph-test-b
|
||||
- name: Build and test service C
|
||||
timeout 60 langgraph test --verbose || (exit "$(($? == 124 ? 0 : $?))")
|
||||
- name: Start service C
|
||||
if: steps.changed-files.outputs.all
|
||||
working-directory: libs/cli/examples/graphs_reqs_a
|
||||
run: |
|
||||
langgraph build -t langgraph-test-c --base-image "langchain/langgraph-trial"
|
||||
timeout 60 python ../../../../.github/scripts/run_langgraph_cli_test.py -t langgraph-test-c
|
||||
- name: Build and test service D
|
||||
timeout 60 langgraph test --verbose || (exit "$(($? == 124 ? 0 : $?))")
|
||||
- name: Start service D
|
||||
if: steps.changed-files.outputs.all
|
||||
working-directory: libs/cli/examples/graphs_reqs_b
|
||||
run: |
|
||||
langgraph build -t langgraph-test-d --base-image "langchain/langgraph-trial"
|
||||
timeout 60 python ../../../../.github/scripts/run_langgraph_cli_test.py -t langgraph-test-d
|
||||
|
||||
- name: Build JS service
|
||||
if: steps.changed-files.outputs.all
|
||||
working-directory: libs/cli/js-examples
|
||||
run: |
|
||||
langgraph build -t langgraph-test-e
|
||||
|
||||
timeout 60 langgraph test --verbose || (exit "$(($? == 124 ? 0 : $?))")
|
||||
|
||||
@@ -42,6 +42,7 @@ jobs:
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
poetry-version: ${{ env.POETRY_VERSION }}
|
||||
working-directory: ${{ inputs.working-directory }}
|
||||
cache-key: lint-${{ inputs.working-directory }}
|
||||
|
||||
- name: Check Poetry File
|
||||
|
||||
@@ -21,7 +21,6 @@ jobs:
|
||||
- "3.10"
|
||||
- "3.11"
|
||||
- "3.12"
|
||||
- "3.13"
|
||||
|
||||
name: "test #${{ matrix.python-version }}"
|
||||
steps:
|
||||
@@ -31,13 +30,8 @@ jobs:
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
poetry-version: ${{ env.POETRY_VERSION }}
|
||||
working-directory: ${{ inputs.working-directory }}
|
||||
cache-key: test-${{ inputs.working-directory }}
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
if: ${{ !github.event.pull_request.head.repo.fork }}
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_RO_TOKEN }}
|
||||
|
||||
- name: Install dependencies
|
||||
shell: bash
|
||||
|
||||
@@ -16,22 +16,14 @@ jobs:
|
||||
- "3.10"
|
||||
- "3.11"
|
||||
- "3.12"
|
||||
- "3.13"
|
||||
core-version:
|
||||
- ">=0.2.39,<0.3.0"
|
||||
- "latest"
|
||||
ff-send-v2:
|
||||
- "false"
|
||||
include:
|
||||
- python-version: "3.11"
|
||||
core-version: ">=0.2.42,<0.3.0"
|
||||
- python-version: "3.11"
|
||||
core-version: "latest"
|
||||
ff-send-v2: "true"
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: libs/langgraph
|
||||
name: "test #${{ matrix.python-version }} (langchain-core: ${{ matrix.core-version }}, ff-send-v2: ${{ matrix.ff-send-v2 }})"
|
||||
name: "test #${{ matrix.python-version }} (langchain-core: ${{ matrix.core-version }})"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python ${{ matrix.python-version }} + Poetry ${{ env.POETRY_VERSION }}
|
||||
@@ -40,12 +32,6 @@ jobs:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
poetry-version: ${{ env.POETRY_VERSION }}
|
||||
cache-key: test-langgraph
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
if: ${{ !github.event.pull_request.head.repo.fork }}
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_RO_TOKEN }}
|
||||
|
||||
- name: Install dependencies
|
||||
shell: bash
|
||||
@@ -57,10 +43,8 @@ jobs:
|
||||
|
||||
- name: Run tests
|
||||
shell: bash
|
||||
env:
|
||||
LANGGRAPH_FF_SEND_V2: ${{ matrix.ff-send-v2 }}
|
||||
run: |
|
||||
make test_parallel
|
||||
make test
|
||||
|
||||
- name: Ensure the tests did not create any additional files
|
||||
shell: bash
|
||||
|
||||
@@ -29,6 +29,7 @@ jobs:
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
poetry-version: ${{ env.POETRY_VERSION }}
|
||||
working-directory: ${{ inputs.working-directory }}
|
||||
cache-key: release
|
||||
|
||||
# We want to keep this build stage *separate* from the release stage,
|
||||
@@ -92,5 +93,3 @@ jobs:
|
||||
# This is *only for CI use* and is *extremely dangerous* otherwise!
|
||||
# https://github.com/pypa/gh-action-pypi-publish#tolerating-release-package-file-duplicates
|
||||
skip-existing: true
|
||||
# Temp workaround since attestations are on by default as of gh-action-pypi-publish v1.11.0
|
||||
attestations: false
|
||||
|
||||
@@ -27,12 +27,6 @@ jobs:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
poetry-version: ${{ env.POETRY_VERSION }}
|
||||
cache-key: test-scheduler-kafka
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
if: ${{ !github.event.pull_request.head.repo.fork }}
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_RO_TOKEN }}
|
||||
|
||||
- name: Install dependencies
|
||||
shell: bash
|
||||
|
||||
@@ -31,7 +31,6 @@ jobs:
|
||||
"libs/cli",
|
||||
"libs/checkpoint",
|
||||
"libs/checkpoint-sqlite",
|
||||
"libs/checkpoint-duckdb",
|
||||
"libs/checkpoint-postgres",
|
||||
"libs/scheduler-kafka",
|
||||
]
|
||||
@@ -48,7 +47,6 @@ jobs:
|
||||
"libs/cli",
|
||||
"libs/checkpoint",
|
||||
"libs/checkpoint-sqlite",
|
||||
"libs/checkpoint-duckdb",
|
||||
"libs/checkpoint-postgres"
|
||||
]
|
||||
uses: ./.github/workflows/_test.yml
|
||||
@@ -109,31 +107,9 @@ jobs:
|
||||
- name: Build
|
||||
run: yarn build
|
||||
|
||||
test-js:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
working-directory:
|
||||
- "libs/sdk-js"
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ${{ matrix.working-directory }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup Node.js (LTS)
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "20"
|
||||
cache: "yarn"
|
||||
cache-dependency-path: ${{ matrix.working-directory }}/yarn.lock
|
||||
- name: Install dependencies
|
||||
run: yarn install
|
||||
- name: Run tests
|
||||
run: yarn test
|
||||
|
||||
ci_success:
|
||||
name: "CI Success"
|
||||
needs: [lint, lint-js, test, test-langgraph, test-scheduler-kafka, integration-test, test-js]
|
||||
needs: [lint, lint-js, test, test-langgraph, test-scheduler-kafka, integration-test]
|
||||
if: |
|
||||
always()
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -44,8 +44,6 @@ jobs:
|
||||
deploy:
|
||||
# needs: run-changed-notebooks
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.MKDOCS_GITHUB_TOKEN }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
@@ -60,14 +58,8 @@ jobs:
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
poetry install --with test --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"
|
||||
poetry install --with docs
|
||||
poetry run pip install -U pytest pytest-check-links langsmith langchain GitPython
|
||||
|
||||
- name: Lint Docs
|
||||
# This step lints the docs using the existing linting set up.
|
||||
@@ -88,15 +80,8 @@ jobs:
|
||||
--check-links-ignore "https://(api|web|docs)\.smith\.langchain\.com/.*" \
|
||||
--check-links-ignore "https://x.com/.*" \
|
||||
--check-links-ignore "https://github\.com/.*" \
|
||||
--check-links-ignore "http://localhost:8123/.*" \
|
||||
--check-links-ignore "http://localhost:2024.*" \
|
||||
--check-links-ignore "http://127.0.0.1:.*" \
|
||||
--check-links-ignore "/.*\.(ipynb|html)$" \
|
||||
--check-links-ignore "https://python\.langchain\.com/.*" \
|
||||
--check-links-ignore "https://openai\.com/.*" \
|
||||
--check-links-ignore "https://pepy\.tech/.*" \
|
||||
--check-links $(find docs/site -name "index.html" | grep -v 'storm/index.html')
|
||||
|
||||
--check-links $(find docs/site -name "index.html" | grep -v 'storm/index.html')
|
||||
else
|
||||
echo "Fetching changes from origin/main..."
|
||||
git fetch origin main
|
||||
@@ -107,9 +92,6 @@ jobs:
|
||||
echo "Running link check on HTML files matching changed notebook files..."
|
||||
poetry run pytest -v \
|
||||
--check-links-ignore "https://(api|web|docs)\.smith\.langchain\.com/.*" \
|
||||
--check-links-ignore "http://localhost:8123/.*" \
|
||||
--check-links-ignore "http://localhost:2024.*" \
|
||||
--check-links-ignore "http://127.0.0.1:.*" \
|
||||
--check-links-ignore "https://x.com/.*" \
|
||||
--check-links-ignore "https://github\.com/.*" \
|
||||
--check-links-ignore "/.*\.(ipynb|html)$" \
|
||||
|
||||
@@ -31,6 +31,7 @@ jobs:
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
poetry-version: ${{ env.POETRY_VERSION }}
|
||||
working-directory: ${{ inputs.working-directory }}
|
||||
cache-key: release
|
||||
|
||||
# We want to keep this build stage *separate* from the release stage,
|
||||
@@ -168,6 +169,7 @@ jobs:
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
poetry-version: ${{ env.POETRY_VERSION }}
|
||||
working-directory: ${{ inputs.working-directory }}
|
||||
|
||||
- name: Import published package
|
||||
shell: bash
|
||||
@@ -254,6 +256,7 @@ jobs:
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
poetry-version: ${{ env.POETRY_VERSION }}
|
||||
working-directory: ${{ inputs.working-directory }}
|
||||
cache-key: release
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
@@ -267,8 +270,6 @@ jobs:
|
||||
packages-dir: ${{ inputs.working-directory }}/dist/
|
||||
verbose: true
|
||||
print-hash: true
|
||||
# Temp workaround since attestations are on by default as of gh-action-pypi-publish v1.11.0
|
||||
attestations: false
|
||||
|
||||
mark-release:
|
||||
needs:
|
||||
@@ -295,6 +296,7 @@ jobs:
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
poetry-version: ${{ env.POETRY_VERSION }}
|
||||
working-directory: ${{ inputs.working-directory }}
|
||||
cache-key: release
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
|
||||
@@ -49,7 +49,7 @@ gain understanding of concepts and how they interact by showing one way to achie
|
||||
|
||||
They should **avoid** giving
|
||||
multiple permutations of ways to achieve that goal in-depth. Choice is burdensome. Instead, they should guide a new user through a recommended path to accomplishing a concrete goal. While the end result of a tutorial does not necessarily need to
|
||||
be completely production-ready, it should be useful and practically satisfy the goal that you clearly stated in the tutorial's introduction.
|
||||
be completely production-ready, it should be useful and practically satisfy the the goal that you clearly stated in the tutorial's introduction.
|
||||
|
||||
To quote the Diataxis website:
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ serve-clean-docs: clean-docs
|
||||
poetry run python -m mkdocs serve -c -f docs/mkdocs.yml --strict -w ./libs/langgraph
|
||||
|
||||
serve-docs: build-typedoc
|
||||
poetry run python -m mkdocs serve -f docs/mkdocs.yml -w ./libs/langgraph -w ./libs/checkpoint -w ./libs/sdk-py --dirty
|
||||
poetry run python -m mkdocs serve -f docs/mkdocs.yml -w ./libs/langgraph --dirty
|
||||
|
||||
clean-docs:
|
||||
find ./docs/docs -name "*.ipynb" -type f -delete
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
⚡ Building language agents as graphs ⚡
|
||||
|
||||
> [!NOTE]
|
||||
> Looking for the JS version? See the [JS repo](https://github.com/langchain-ai/langgraphjs) and the [JS docs](https://langchain-ai.github.io/langgraphjs/).
|
||||
> Looking for the JS version? Click [here](https://github.com/langchain-ai/langgraphjs) ([JS docs](https://langchain-ai.github.io/langgraphjs/)).
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
LangGraph is inspired by [Pregel](https://research.google/pubs/pub37252/) and [Apache Beam](https://beam.apache.org/). The public interface draws inspiration from [NetworkX](https://networkx.org/documentation/latest/). LangGraph is built by LangChain Inc, the creators of LangChain, but can be used without LangChain.
|
||||
|
||||
[LangGraph Platform](https://langchain-ai.github.io/langgraph/concepts/langgraph_platform) is infrastructure for deploying LangGraph agents. It is a commercial solution for deploying agentic applications to production, built on the open-source LangGraph framework. The LangGraph Platform consists of several components that work together to support the development, deployment, debugging, and monitoring of LangGraph applications: [LangGraph Server](https://langchain-ai.github.io/langgraph/concepts/langgraph_server) (APIs), [LangGraph SDKs](https://langchain-ai.github.io/langgraph/concepts/sdk) (clients for the APIs), [LangGraph CLI](https://langchain-ai.github.io/langgraph/concepts/langgraph_cli) (command line tool for building the server), [LangGraph Studio](https://langchain-ai.github.io/langgraph/concepts/langgraph_studio) (UI/debugger),
|
||||
|
||||
To learn more about LangGraph, check out our first LangChain Academy course, *Introduction to LangGraph*, available for free [here](https://academy.langchain.com/courses/intro-to-langgraph).
|
||||
|
||||
### Key Features
|
||||
@@ -28,16 +26,6 @@ To learn more about LangGraph, check out our first LangChain Academy course, *In
|
||||
- **Streaming Support**: Stream outputs as they are produced by each node (including token streaming).
|
||||
- **Integration with LangChain**: LangGraph integrates seamlessly with [LangChain](https://github.com/langchain-ai/langchain/) and [LangSmith](https://docs.smith.langchain.com/) (but does not require them).
|
||||
|
||||
### LangGraph Platform
|
||||
|
||||
LangGraph Platform is a commercial solution for deploying agentic applications to production, built on the open-source LangGraph framework.
|
||||
Here are some common issues that arise in complex deployments, which LangGraph Platform addresses:
|
||||
|
||||
- **Streaming support**: LangGraph Server provides [multiple streaming modes](https://langchain-ai.github.io/langgraph/concepts/streaming) optimized for various application needs
|
||||
- **Background runs**: Runs agents asynchronously in the background
|
||||
- **Support for long running agents**: Infrastructure that can handle long running processes
|
||||
- **[Double texting](https://langchain-ai.github.io/langgraph/concepts/double_texting)**: Handle the case where you get two messages from the user before the agent can respond
|
||||
- **Handle burstiness**: Task queue for ensuring requests are handled consistently without loss, even under heavy loads
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -72,7 +60,7 @@ from typing import Annotated, Literal, TypedDict
|
||||
from langchain_core.messages import HumanMessage
|
||||
from langchain_anthropic import ChatAnthropic
|
||||
from langchain_core.tools import tool
|
||||
from langgraph.checkpoint.memory import MemorySaver
|
||||
from langgraph.checkpoint.memory import InMemorySaver
|
||||
from langgraph.graph import END, START, StateGraph, MessagesState
|
||||
from langgraph.prebuilt import ToolNode
|
||||
|
||||
@@ -137,7 +125,7 @@ workflow.add_conditional_edges(
|
||||
workflow.add_edge("tools", 'agent')
|
||||
|
||||
# Initialize memory to persist state between graph runs
|
||||
checkpointer = MemorySaver()
|
||||
checkpointer = InMemorySaver()
|
||||
|
||||
# Finally, we compile it!
|
||||
# This compiles it into a LangChain Runnable,
|
||||
@@ -213,7 +201,7 @@ final_state["messages"][-1].content
|
||||
<summary>Compile the graph.</summary>
|
||||
|
||||
- When we compile the graph, we turn it into a LangChain [Runnable](https://python.langchain.com/v0.2/docs/concepts/#runnable-interface), which automatically enables calling `.invoke()`, `.stream()` and `.batch()` with your inputs
|
||||
- We can also optionally pass checkpointer object for persisting state between graph runs, and enabling memory, human-in-the-loop workflows, time travel and more. In our case we use `MemorySaver` - a simple in-memory checkpointer
|
||||
- We can also optionally pass checkpointer object for persisting state between graph runs, and enabling memory, human-in-the-loop workflows, time travel and more. In our case we use `InMemorySaver` - a simple in-memory checkpointer
|
||||
</details>
|
||||
|
||||
6. <details>
|
||||
@@ -238,7 +226,7 @@ final_state["messages"][-1].content
|
||||
* [How-to Guides](https://langchain-ai.github.io/langgraph/how-tos/): Accomplish specific things within LangGraph, from streaming, to adding memory & persistence, to common design patterns (branching, subgraphs, etc.), these are the place to go if you want to copy and run a specific code snippet.
|
||||
* [Conceptual Guides](https://langchain-ai.github.io/langgraph/concepts/high_level/): In-depth explanations of the key concepts and principles behind LangGraph, such as nodes, edges, state and more.
|
||||
* [API Reference](https://langchain-ai.github.io/langgraph/reference/graphs/): Review important classes and methods, simple examples of how to use the graph and checkpointing APIs, higher-level prebuilt components and more.
|
||||
* [LangGraph Platform](https://langchain-ai.github.io/langgraph/concepts/#langgraph-platform): LangGraph Platform is a commercial solution for deploying agentic applications in production, built on the open-source LangGraph framework.
|
||||
* [Cloud (beta)](https://langchain-ai.github.io/langgraph/cloud/): With one click, deploy LangGraph applications to LangGraph Cloud.
|
||||
|
||||
## Contributing
|
||||
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
import functools
|
||||
|
||||
from urllib3 import __version__ as urllib3version # type: ignore[import-untyped]
|
||||
from urllib3 import connection # type: ignore[import-untyped]
|
||||
|
||||
|
||||
def _ensure_str(s, encoding="utf-8", errors="strict") -> str:
|
||||
if isinstance(s, str):
|
||||
return s
|
||||
|
||||
if isinstance(s, bytes):
|
||||
return s.decode(encoding, errors)
|
||||
return str(s)
|
||||
|
||||
|
||||
# Copied from https://github.com/urllib3/urllib3/blob/1c994dfc8c5d5ecaee8ed3eb585d4785f5febf6e/src/urllib3/connection.py#L231
|
||||
def request(self, method, url, body=None, headers=None):
|
||||
"""Make the request.
|
||||
|
||||
This function is based on the urllib3 request method, with modifications
|
||||
to handle potential issues when using vcrpy in concurrent workloads.
|
||||
|
||||
Args:
|
||||
self: The HTTPConnection instance.
|
||||
method (str): The HTTP method (e.g., 'GET', 'POST').
|
||||
url (str): The URL for the request.
|
||||
body (Optional[Any]): The body of the request.
|
||||
headers (Optional[dict]): Headers to send with the request.
|
||||
|
||||
Returns:
|
||||
The result of calling the parent request method.
|
||||
"""
|
||||
# Update the inner socket's timeout value to send the request.
|
||||
# This only triggers if the connection is re-used.
|
||||
if getattr(self, "sock", None) is not None:
|
||||
self.sock.settimeout(self.timeout)
|
||||
|
||||
if headers is None:
|
||||
headers = {}
|
||||
else:
|
||||
# Avoid modifying the headers passed into .request()
|
||||
headers = headers.copy()
|
||||
if "user-agent" not in (_ensure_str(k.lower()) for k in headers):
|
||||
headers["User-Agent"] = connection._get_default_user_agent()
|
||||
# The above is all the same ^^^
|
||||
# The following is different:
|
||||
return self._parent_request(method, url, body=body, headers=headers)
|
||||
|
||||
|
||||
_PATCHED = False
|
||||
|
||||
|
||||
def patch_urllib3():
|
||||
"""Patch the request method of urllib3 to avoid type errors when using vcrpy.
|
||||
|
||||
In concurrent workloads (such as the tracing background queue), the
|
||||
connection pool can get in a state where an HTTPConnection is created
|
||||
before vcrpy patches the HTTPConnection class. In urllib3 >= 2.0 this isn't
|
||||
a problem since they use the proper super().request(...) syntax, but in older
|
||||
versions, super(HTTPConnection, self).request is used, resulting in a TypeError
|
||||
since self is no longer a subclass of "HTTPConnection" (which at this point
|
||||
is vcr.stubs.VCRConnection).
|
||||
|
||||
This method patches the class to fix the super() syntax to avoid mixed inheritance.
|
||||
In the case of the LangSmith tracing logic, it doesn't really matter since we always
|
||||
exclude cache checks for calls to LangSmith.
|
||||
|
||||
The patch is only applied for urllib3 versions older than 2.0.
|
||||
"""
|
||||
global _PATCHED
|
||||
if _PATCHED:
|
||||
return
|
||||
from packaging import version
|
||||
|
||||
if version.parse(urllib3version) >= version.parse("2.0"):
|
||||
_PATCHED = True
|
||||
return
|
||||
|
||||
# Lookup the parent class and its request method
|
||||
parent_class = connection.HTTPConnection.__bases__[0]
|
||||
parent_request = parent_class.request
|
||||
|
||||
def new_request(self, *args, **kwargs):
|
||||
"""Handle parent request.
|
||||
|
||||
This method binds the parent's request method to self and then
|
||||
calls our modified request function.
|
||||
"""
|
||||
self._parent_request = functools.partial(parent_request, self)
|
||||
return request(self, *args, **kwargs)
|
||||
|
||||
connection.HTTPConnection.request = new_request
|
||||
_PATCHED = True
|
||||
@@ -24,7 +24,7 @@ export -f execute_notebook
|
||||
|
||||
# Check if custom notebook paths are provided
|
||||
if [ $# -gt 0 ]; then
|
||||
notebooks=$(echo "$@" | tr ' ' '\n' | grep -vFf <(echo "$SKIP_NOTEBOOKS"))
|
||||
notebooks="$@"
|
||||
else
|
||||
# Find all notebooks and filter out those in the skip list
|
||||
notebooks=$(find docs/docs/tutorials docs/docs/how-tos -name "*.ipynb" | grep -v ".ipynb_checkpoints" | grep -vFf <(echo "$SKIP_NOTEBOOKS"))
|
||||
|
||||
@@ -1,290 +0,0 @@
|
||||
import importlib
|
||||
import inspect
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
from typing import List, Literal, Optional
|
||||
from typing_extensions import TypedDict
|
||||
|
||||
|
||||
from functools import lru_cache
|
||||
|
||||
import nbformat
|
||||
from nbconvert.preprocessors import Preprocessor
|
||||
|
||||
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger(__name__)
|
||||
# Base URL for all class documentation
|
||||
_LANGCHAIN_API_REFERENCE = "https://python.langchain.com/api_reference/"
|
||||
_LANGGRAPH_API_REFERENCE = "https://langchain-ai.github.io/langgraph/reference/"
|
||||
|
||||
|
||||
# (alias/re-exported modules, source module, class, docs namespace)
|
||||
MANUAL_API_REFERENCES_LANGGRAPH = [
|
||||
(
|
||||
["langgraph.prebuilt"],
|
||||
"langgraph.prebuilt.chat_agent_executor",
|
||||
"create_react_agent",
|
||||
"prebuilt",
|
||||
),
|
||||
(["langgraph.prebuilt"], "langgraph.prebuilt.tool_node", "ToolNode", "prebuilt"),
|
||||
(
|
||||
["langgraph.prebuilt"],
|
||||
"langgraph.prebuilt.tool_node",
|
||||
"tools_condition",
|
||||
"prebuilt",
|
||||
),
|
||||
(
|
||||
["langgraph.prebuilt"],
|
||||
"langgraph.prebuilt.tool_node",
|
||||
"InjectedState",
|
||||
"prebuilt",
|
||||
),
|
||||
# Graph
|
||||
(["langgraph.graph"], "langgraph.graph.message", "add_messages", "graphs"),
|
||||
(["langgraph.graph"], "langgraph.graph.state", "StateGraph", "graphs"),
|
||||
(["langgraph.graph"], "langgraph.graph.state", "CompiledStateGraph", "graphs"),
|
||||
([], "langgraph.types", "StreamMode", "types"),
|
||||
(["langgraph.graph"], "langgraph.constants", "START", "constants"),
|
||||
(["langgraph.graph"], "langgraph.constants", "END", "constants"),
|
||||
(["langgraph.constants"], "langgraph.types", "Send", "types"),
|
||||
(["langgraph.constants"], "langgraph.types", "Interrupt", "types"),
|
||||
(["langgraph.constants"], "langgraph.types", "interrupt", "types"),
|
||||
(["langgraph.constants"], "langgraph.types", "Command", "types"),
|
||||
([], "langgraph.types", "RetryPolicy", "types"),
|
||||
([], "langgraph.checkpoint.base", "Checkpoint", "checkpoints"),
|
||||
([], "langgraph.checkpoint.base", "CheckpointMetadata", "checkpoints"),
|
||||
([], "langgraph.checkpoint.base", "BaseCheckpointSaver", "checkpoints"),
|
||||
([], "langgraph.checkpoint.base", "SerializerProtocol", "checkpoints"),
|
||||
([], "langgraph.checkpoint.serde.jsonplus", "JsonPlusSerializer", "checkpoints"),
|
||||
([], "langgraph.checkpoint.memory", "MemorySaver", "checkpoints"),
|
||||
([], "langgraph.checkpoint.sqlite.aio", "AsyncSqliteSaver", "checkpoints"),
|
||||
([], "langgraph.checkpoint.sqlite", "SqliteSaver", "checkpoints"),
|
||||
([], "langgraph.checkpoint.postgres.aio", "AsyncPostgresSaver", "checkpoints"),
|
||||
([], "langgraph.checkpoint.postgres", "PostgresSaver", "checkpoints"),
|
||||
]
|
||||
|
||||
WELL_KNOWN_LANGGRAPH_OBJECTS = {
|
||||
(module_, class_): (source_module, namespace)
|
||||
for (modules, source_module, class_, namespace) in MANUAL_API_REFERENCES_LANGGRAPH
|
||||
for module_ in modules + [source_module]
|
||||
}
|
||||
|
||||
|
||||
def _make_regular_expression(pkg_prefix: str) -> re.Pattern:
|
||||
if not pkg_prefix.isidentifier():
|
||||
raise ValueError(f"Invalid package prefix: {pkg_prefix}")
|
||||
return re.compile(
|
||||
r"from\s+(" + pkg_prefix + "(?:_\w+)?(?:\.\w+)*?)\s+import\s+"
|
||||
r"((?:\w+(?:,\s*)?)*" # Match zero or more words separated by a comma+optional ws
|
||||
r"(?:\s*\(.*?\))?)", # Match optional parentheses block
|
||||
re.DOTALL, # Match newlines as well
|
||||
)
|
||||
|
||||
|
||||
# Regular expression to match langchain import lines
|
||||
_IMPORT_LANGCHAIN_RE = _make_regular_expression("langchain")
|
||||
_IMPORT_LANGGRAPH_RE = _make_regular_expression("langgraph")
|
||||
|
||||
|
||||
|
||||
|
||||
@lru_cache(maxsize=10_000)
|
||||
def _get_full_module_name(module_path: str, class_name: str) -> Optional[str]:
|
||||
"""Get full module name using inspect, with LRU cache to memoize results."""
|
||||
try:
|
||||
module = importlib.import_module(module_path)
|
||||
class_ = getattr(module, class_name)
|
||||
module = inspect.getmodule(class_)
|
||||
if module is None:
|
||||
# For constants, inspect.getmodule() might return None
|
||||
# In this case, we'll return the original module_path
|
||||
return module_path
|
||||
return module.__name__
|
||||
except AttributeError as e:
|
||||
logger.warning(f"API Reference: Could not find module for {class_name}, {e}")
|
||||
return None
|
||||
except ImportError as e:
|
||||
logger.warning(f"API Reference: Failed to load for class {class_name}, {e}")
|
||||
return None
|
||||
|
||||
def _get_doc_title(data: str, file_name: str) -> str:
|
||||
try:
|
||||
return re.findall(r"^#\s*(.*)", data, re.MULTILINE)[0]
|
||||
except IndexError:
|
||||
pass
|
||||
# Parse the rst-style titles
|
||||
try:
|
||||
return re.findall(r"^(.*)\n=+\n", data, re.MULTILINE)[0]
|
||||
except IndexError:
|
||||
return file_name
|
||||
|
||||
|
||||
class ImportInformation(TypedDict):
|
||||
imported: str # The name of the class that was imported.
|
||||
source: str # The full module path from which the class was imported.
|
||||
docs: str # The URL pointing to the class's documentation.
|
||||
title: str # The title of the document where the import is used.
|
||||
|
||||
|
||||
def _get_imports(
|
||||
code: str, doc_title: str, package_ecosystem: Literal["langchain", "langgraph"]
|
||||
) -> List[ImportInformation]:
|
||||
"""Get imports from the given code block.
|
||||
|
||||
Args:
|
||||
code: Python code block from which to extract imports
|
||||
doc_title: Title of the document
|
||||
package_ecosystem: "langchain" or "langgraph". The two live in different
|
||||
repositories and have separate documentation sites.
|
||||
|
||||
Returns:
|
||||
List of import information for the given code block
|
||||
"""
|
||||
imports = []
|
||||
|
||||
if package_ecosystem == "langchain":
|
||||
pattern = _IMPORT_LANGCHAIN_RE
|
||||
elif package_ecosystem == "langgraph":
|
||||
pattern = _IMPORT_LANGGRAPH_RE
|
||||
else:
|
||||
raise ValueError(f"Invalid package ecosystem: {package_ecosystem}")
|
||||
|
||||
for import_match in pattern.finditer(code):
|
||||
module = import_match.group(1)
|
||||
if "pydantic_v1" in module:
|
||||
continue
|
||||
imports_str = (
|
||||
import_match.group(2).replace("(\n", "").replace("\n)", "")
|
||||
) # Handle newlines within parentheses
|
||||
# remove any newline and spaces, then split by comma
|
||||
imported_classes = [
|
||||
imp.strip()
|
||||
for imp in re.split(r",\s*", imports_str.replace("\n", ""))
|
||||
if imp.strip()
|
||||
]
|
||||
for class_name in imported_classes:
|
||||
module_path = _get_full_module_name(module, class_name)
|
||||
if not module_path:
|
||||
continue
|
||||
if len(module_path.split(".")) < 2:
|
||||
continue
|
||||
|
||||
if package_ecosystem == "langchain":
|
||||
pkg = module_path.split(".")[0].replace("langchain_", "")
|
||||
top_level_mod = module_path.split(".")[1]
|
||||
|
||||
url = (
|
||||
_LANGCHAIN_API_REFERENCE
|
||||
+ pkg
|
||||
+ "/"
|
||||
+ top_level_mod
|
||||
+ "/"
|
||||
+ module_path
|
||||
+ "."
|
||||
+ class_name
|
||||
+ ".html"
|
||||
)
|
||||
elif package_ecosystem == "langgraph":
|
||||
if (module, class_name) not in WELL_KNOWN_LANGGRAPH_OBJECTS:
|
||||
# Likely not documented yet
|
||||
continue
|
||||
|
||||
source_module, namespace = WELL_KNOWN_LANGGRAPH_OBJECTS[
|
||||
(module, class_name)
|
||||
]
|
||||
url = (
|
||||
_LANGGRAPH_API_REFERENCE
|
||||
+ namespace
|
||||
+ "/#"
|
||||
+ source_module
|
||||
+ "."
|
||||
+ class_name
|
||||
)
|
||||
else:
|
||||
raise ValueError(f"Invalid package ecosystem: {package_ecosystem}")
|
||||
|
||||
# Add the import information to our list
|
||||
imports.append(
|
||||
{
|
||||
"imported": class_name,
|
||||
"source": module,
|
||||
"docs": url,
|
||||
"title": doc_title,
|
||||
}
|
||||
)
|
||||
|
||||
return imports
|
||||
|
||||
|
||||
def get_imports(code: str, doc_title: str) -> List[ImportInformation]:
|
||||
"""Retrieve all import references from the given code for specified ecosystems.
|
||||
|
||||
Args:
|
||||
code: The source code from which to extract import references.
|
||||
doc_title: The documentation title associated with the code.
|
||||
|
||||
Returns:
|
||||
A list of import information for each import found.
|
||||
"""
|
||||
ecosystems = ["langchain", "langgraph"]
|
||||
all_imports = []
|
||||
for package_ecosystem in ecosystems:
|
||||
all_imports.extend(_get_imports(code, doc_title, package_ecosystem))
|
||||
return all_imports
|
||||
|
||||
|
||||
def update_markdown_with_imports(markdown: str) -> str:
|
||||
"""Update markdown to include API reference links for imports in Python code blocks.
|
||||
|
||||
This function scans the markdown content for Python code blocks, extracts any imports, and appends links to their API documentation.
|
||||
|
||||
Args:
|
||||
markdown: The markdown content to process.
|
||||
|
||||
Returns:
|
||||
Updated markdown with API reference links appended to Python code blocks.
|
||||
|
||||
Example:
|
||||
Given a markdown with a Python code block:
|
||||
|
||||
```python
|
||||
from langchain.nlp import TextGenerator
|
||||
```
|
||||
This function will append an API reference link to the `TextGenerator` class from the `langchain.nlp` module if it's recognized.
|
||||
"""
|
||||
code_block_pattern = re.compile(
|
||||
r'(?P<indent>[ \t]*)```(?P<language>python|py)\n(?P<code>.*?)\n(?P=indent)```', re.DOTALL
|
||||
)
|
||||
|
||||
def replace_code_block(match: re.Match) -> str:
|
||||
"""Replace the matched code block with additional API reference links if imports are found.
|
||||
|
||||
Args:
|
||||
match (re.Match): The regex match object containing the code block.
|
||||
|
||||
Returns:
|
||||
str: The modified code block with API reference links appended if applicable.
|
||||
"""
|
||||
indent = match.group('indent')
|
||||
code_block = match.group('code')
|
||||
language = match.group('language') # Preserve the language from the regex match
|
||||
# Retrieve import information from the code block
|
||||
imports = get_imports(code_block, "__unused__")
|
||||
|
||||
original_code_block = match.group(0)
|
||||
# If no imports are found, return the original code block
|
||||
if not imports:
|
||||
return original_code_block
|
||||
|
||||
# Generate API reference links for each import
|
||||
api_links = ' | '.join(
|
||||
f'<a href="{imp["docs"]}">{imp["imported"]}</a>' for imp in imports
|
||||
)
|
||||
# Return the code block with appended API reference links
|
||||
return f'{original_code_block}\n\n{indent}API Reference: {api_links}'
|
||||
|
||||
# Apply the replace_code_block function to all matches in the markdown
|
||||
updated_markdown = code_block_pattern.sub(replace_code_block, markdown)
|
||||
return updated_markdown
|
||||
@@ -1,123 +0,0 @@
|
||||
import os
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
import nbformat
|
||||
from nbconvert.exporters import MarkdownExporter
|
||||
from nbconvert.preprocessors import Preprocessor
|
||||
|
||||
|
||||
class EscapePreprocessor(Preprocessor):
|
||||
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"(?<!!)\[([^\]]*)\]\((?![^\)]*//)([^)]*)(?:\.ipynb)?\)",
|
||||
r'<a href="\2">\1</a>',
|
||||
cell.source,
|
||||
)
|
||||
# Fix image paths in <img> tags
|
||||
cell.source = re.sub(
|
||||
r'<img\s+src="\.?/img/([^"]+)"', r'<img src="../img/\1"', cell.source
|
||||
)
|
||||
|
||||
elif cell.cell_type == "code":
|
||||
# escape ``` in code
|
||||
cell.source = cell.source.replace("```", r"\`\`\`")
|
||||
# escape ``` in output
|
||||
if "outputs" in cell:
|
||||
filter_out = set()
|
||||
for i, output in enumerate(cell["outputs"]):
|
||||
if "text" in output:
|
||||
if not output["text"].strip():
|
||||
filter_out.add(i)
|
||||
continue
|
||||
|
||||
value = output["text"].replace("```", r"\`\`\`")
|
||||
# handle a funky case w/ references in text
|
||||
value = re.sub(r"\[(\d+)\](?=\[(\d+)\])", r"[\1]\\", value)
|
||||
output["text"] = value
|
||||
elif "data" in output:
|
||||
for key, value in output["data"].items():
|
||||
if isinstance(value, str):
|
||||
value = value.replace("```", r"\`\`\`")
|
||||
# handle a funky case w/ references in text
|
||||
output["data"][key] = re.sub(
|
||||
r"\[(\d+)\](?=\[(\d+)\])", r"[\1]\\", value
|
||||
)
|
||||
cell["outputs"] = [
|
||||
output
|
||||
for i, output in enumerate(cell["outputs"])
|
||||
if i not in filter_out
|
||||
]
|
||||
|
||||
return cell, resources
|
||||
|
||||
|
||||
class ExtractAttachmentsPreprocessor(Preprocessor):
|
||||
"""
|
||||
Extracts all of the outputs from the notebook file. The extracted
|
||||
outputs are returned in the 'resources' dictionary.
|
||||
"""
|
||||
|
||||
def preprocess_cell(self, cell, resources, cell_index):
|
||||
"""
|
||||
Apply a transformation on each cell,
|
||||
Parameters
|
||||
----------
|
||||
cell : NotebookNode cell
|
||||
Notebook cell being processed
|
||||
resources : dictionary
|
||||
Additional resources used in the conversion process. Allows
|
||||
preprocessors to pass variables into the Jinja engine.
|
||||
cell_index : int
|
||||
Index of the cell being processed (see base.py)
|
||||
"""
|
||||
|
||||
# Get files directory if it has been specified
|
||||
|
||||
# Make sure outputs key exists
|
||||
if not isinstance(resources["outputs"], dict):
|
||||
resources["outputs"] = {}
|
||||
|
||||
# Loop through all of the attachments in the cell
|
||||
for name, attach in cell.get("attachments", {}).items():
|
||||
for mime, data in attach.items():
|
||||
if mime not in {
|
||||
"image/png",
|
||||
"image/jpeg",
|
||||
"image/svg+xml",
|
||||
"application/pdf",
|
||||
}:
|
||||
continue
|
||||
|
||||
# attachments are pre-rendered. Only replace markdown-formatted
|
||||
# images with the following logic
|
||||
attach_str = f"({name})"
|
||||
if attach_str in cell.source:
|
||||
data = f"(data:{mime};base64,{data})"
|
||||
cell.source = cell.source.replace(attach_str, data)
|
||||
|
||||
return cell, resources
|
||||
|
||||
|
||||
exporter = MarkdownExporter(
|
||||
preprocessors=[
|
||||
EscapePreprocessor,
|
||||
ExtractAttachmentsPreprocessor,
|
||||
],
|
||||
template_name="mdoutput",
|
||||
extra_template_basedirs=[
|
||||
os.path.join(os.path.dirname(__file__), "notebook_convert_templates")
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
def convert_notebook(
|
||||
notebook_path: Path,
|
||||
) -> Path:
|
||||
with open(notebook_path) as f:
|
||||
nb = nbformat.read(f, as_version=4)
|
||||
|
||||
body, _ = exporter.from_notebook_node(nb)
|
||||
return body
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"mimetypes": {
|
||||
"text/markdown": true
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
{% extends 'markdown/index.md.j2' %}
|
||||
|
||||
{%- block traceback_line -%}
|
||||
```output
|
||||
{{ line.rstrip() | strip_ansi }}
|
||||
```
|
||||
{%- endblock traceback_line -%}
|
||||
|
||||
{%- block stream -%}
|
||||
```output
|
||||
{{ output.text.rstrip() }}
|
||||
```
|
||||
{%- endblock stream -%}
|
||||
|
||||
{%- block data_text scoped -%}
|
||||
```output
|
||||
{{ output.data['text/plain'].rstrip() }}
|
||||
```
|
||||
{%- endblock data_text -%}
|
||||
|
||||
{%- block data_html scoped -%}
|
||||
```html
|
||||
{{ output.data['text/html'] | safe }}
|
||||
```
|
||||
{%- endblock data_html -%}
|
||||
|
||||
{%- block data_jpg scoped -%}
|
||||

|
||||
{%- endblock data_jpg -%}
|
||||
|
||||
{%- block data_png scoped -%}
|
||||

|
||||
{%- endblock data_png -%}
|
||||
@@ -1,120 +0,0 @@
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
from typing import Any, Dict
|
||||
|
||||
from mkdocs.structure.files import Files, File
|
||||
from mkdocs.structure.pages import Page
|
||||
|
||||
from notebook_convert import convert_notebook
|
||||
from generate_api_reference_links import update_markdown_with_imports
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logging.basicConfig()
|
||||
logger.setLevel(logging.INFO)
|
||||
DISABLED = os.getenv("DISABLE_NOTEBOOK_CONVERT") in ("1", "true", "True")
|
||||
|
||||
|
||||
class NotebookFile(File):
|
||||
def is_documentation_page(self):
|
||||
return True
|
||||
|
||||
|
||||
def on_files(files: Files, **kwargs: Dict[str, Any]):
|
||||
if DISABLED:
|
||||
return files
|
||||
new_files = Files([])
|
||||
for file in files:
|
||||
if file.src_path.endswith(".ipynb"):
|
||||
new_file = NotebookFile(
|
||||
path=file.src_path,
|
||||
src_dir=file.src_dir,
|
||||
dest_dir=file.dest_dir,
|
||||
use_directory_urls=file.use_directory_urls,
|
||||
)
|
||||
new_files.append(new_file)
|
||||
else:
|
||||
new_files.append(file)
|
||||
return new_files
|
||||
|
||||
|
||||
def _highlight_code_blocks(markdown: str) -> str:
|
||||
"""Find code blocks with highlight comments and add hl_lines attribute.
|
||||
|
||||
Args:
|
||||
markdown: The markdown content to process.
|
||||
|
||||
Returns:
|
||||
updated Markdown code with code blocks containing highlight comments
|
||||
updated to use the hl_lines attribute.
|
||||
"""
|
||||
# Pattern to find code blocks with highlight comments and without
|
||||
# existing hl_lines for Python and JavaScript
|
||||
# Pattern to find code blocks with highlight comments, handling optional indentation
|
||||
code_block_pattern = re.compile(
|
||||
r"(?P<indent>[ \t]*)```(?P<language>py|python|js|javascript)(?!\s+hl_lines=)\n"
|
||||
r"(?P<code>((?:.*\n)*?))" # Capture the code inside the block using named group
|
||||
r"(?P=indent)```" # Match closing backticks with the same indentation
|
||||
)
|
||||
|
||||
def replace_highlight_comments(match: re.Match) -> str:
|
||||
indent = match.group("indent")
|
||||
language = match.group("language")
|
||||
code_block = match.group("code")
|
||||
lines = code_block.split("\n")
|
||||
highlighted_lines = []
|
||||
|
||||
# Skip initial empty lines
|
||||
while lines and not lines[0].strip():
|
||||
lines.pop(0)
|
||||
|
||||
lines_to_keep = []
|
||||
|
||||
comment_syntax = (
|
||||
"# highlight-next-line"
|
||||
if language in ["py", "python"]
|
||||
else "// highlight-next-line"
|
||||
)
|
||||
|
||||
for line in lines:
|
||||
if comment_syntax in line:
|
||||
count = len(lines_to_keep) + 1
|
||||
highlighted_lines.append(str(count))
|
||||
else:
|
||||
lines_to_keep.append(line)
|
||||
|
||||
# Reconstruct the new code block
|
||||
new_code_block = "\n".join(lines_to_keep)
|
||||
|
||||
if highlighted_lines:
|
||||
return (
|
||||
f'{indent}```{language} hl_lines="{" ".join(highlighted_lines)}"\n'
|
||||
# The indent and terminating \n is already included in the code block
|
||||
f'{new_code_block}'
|
||||
f'{indent}```'
|
||||
)
|
||||
else:
|
||||
return (
|
||||
f"{indent}```{language}\n"
|
||||
# The indent and terminating \n is already included in the code block
|
||||
f"{new_code_block}"
|
||||
f"{indent}```"
|
||||
)
|
||||
|
||||
# Replace all code blocks in the markdown
|
||||
markdown = code_block_pattern.sub(replace_highlight_comments, markdown)
|
||||
return markdown
|
||||
|
||||
|
||||
def on_page_markdown(markdown: str, page: Page, **kwargs: Dict[str, Any]):
|
||||
if DISABLED:
|
||||
return markdown
|
||||
if page.file.src_path.endswith(".ipynb"):
|
||||
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
|
||||
markdown = update_markdown_with_imports(markdown)
|
||||
# Apply highlight comments to code blocks
|
||||
markdown = _highlight_code_blocks(markdown)
|
||||
return markdown
|
||||
@@ -36,16 +36,14 @@ NOTEBOOKS_NO_EXECUTION = [
|
||||
"docs/docs/tutorials/rag/langgraph_self_rag_local.ipynb",
|
||||
# this loads a massive dataset from gcp
|
||||
"docs/docs/tutorials/usaco/usaco.ipynb",
|
||||
# TODO: figure out why autogen notebook is not runnable (they are just hanging. possible due to code execution?)
|
||||
"docs/docs/how-tos/autogen-integration.ipynb",
|
||||
# TODO: need to update these notebooks to make sure they are runnable in CI
|
||||
"docs/docs/tutorials/storm/storm.ipynb", # issues only when running with VCR
|
||||
"docs/docs/tutorials/lats/lats.ipynb", # issues only when running with VCR
|
||||
"docs/docs/tutorials/multi_agent/hierarchical_agent_teams.ipynb", # taking a very long time to run
|
||||
"docs/docs/tutorials/customer-support/customer-support.ipynb", # user input - update
|
||||
"docs/docs/tutorials/rag/langgraph_crag.ipynb", # flakiness from tavily
|
||||
"docs/docs/tutorials/rag/langgraph_adaptive_rag.ipynb", # Cannot create a consistent method resolution error from VCR
|
||||
"docs/docs/how-tos/map-reduce.ipynb", # flakiness from structured output, only when running with VCR
|
||||
"docs/docs/tutorials/tot/tot.ipynb",
|
||||
"docs/docs/how-tos/visualization.ipynb"
|
||||
"docs/docs/how-tos/map-reduce.ipynb" # flakiness from structured output, only when running with VCR
|
||||
]
|
||||
|
||||
|
||||
@@ -72,13 +70,10 @@ def is_comment(code: str) -> bool:
|
||||
return code.strip().startswith("#")
|
||||
|
||||
|
||||
def has_blocklisted_command(code: str, metadata: dict) -> bool:
|
||||
if 'hide_from_vcr' in metadata:
|
||||
return True
|
||||
|
||||
def has_blocklisted_command(code: str) -> bool:
|
||||
code = code.strip()
|
||||
for blocklisted_pattern in BLOCKLIST_COMMANDS:
|
||||
if blocklisted_pattern in code:
|
||||
for blocklisted_command in BLOCKLIST_COMMANDS:
|
||||
if blocklisted_command in code:
|
||||
return True
|
||||
return False
|
||||
|
||||
@@ -88,7 +83,6 @@ def add_vcr_to_notebook(
|
||||
) -> nbformat.NotebookNode:
|
||||
"""Inject `with vcr.cassette` into each code cell of the notebook."""
|
||||
|
||||
uses_langsmith = False
|
||||
# Inject VCR context manager into each code cell
|
||||
for idx, cell in enumerate(notebook.cells):
|
||||
if cell.cell_type != "code":
|
||||
@@ -114,7 +108,7 @@ def add_vcr_to_notebook(
|
||||
if all(is_comment(line) or not line.strip() for line in lines):
|
||||
continue
|
||||
|
||||
if has_blocklisted_command(cell.source, cell.metadata):
|
||||
if has_blocklisted_command(cell.source):
|
||||
continue
|
||||
|
||||
cell_id = cell.get("id", idx)
|
||||
@@ -123,9 +117,6 @@ def add_vcr_to_notebook(
|
||||
f" {line}" for line in lines
|
||||
)
|
||||
|
||||
if any("hub.pull" in line or "from langsmith import" in line for line in lines):
|
||||
uses_langsmith = True
|
||||
|
||||
# Add import statement
|
||||
vcr_import_lines = [
|
||||
"import nest_asyncio",
|
||||
@@ -134,8 +125,6 @@ def add_vcr_to_notebook(
|
||||
"import msgpack",
|
||||
"import base64",
|
||||
"import zlib",
|
||||
"import os",
|
||||
"os.environ.pop(\"LANGCHAIN_TRACING_V2\", None)",
|
||||
"custom_vcr = vcr.VCR()",
|
||||
"",
|
||||
"def compress_data(data, compression_level=9):",
|
||||
@@ -158,15 +147,6 @@ def add_vcr_to_notebook(
|
||||
"custom_vcr.register_serializer('advanced_compressed', AdvancedCompressedSerializer())",
|
||||
"custom_vcr.serializer = 'advanced_compressed'",
|
||||
]
|
||||
if uses_langsmith:
|
||||
vcr_import_lines.extend(
|
||||
# patch urllib3 to handle vcr errors, see more here:
|
||||
# https://github.com/langchain-ai/langsmith-sdk/blob/main/python/langsmith/_internal/_patch.py
|
||||
"import sys",
|
||||
f"sys.path.insert(0, '{os.path.join(DOCS_PATH, '_scripts')}')",
|
||||
"import _patch as patch_urllib3",
|
||||
"patch_urllib3.patch_urllib3()",
|
||||
)
|
||||
import_cell = nbformat.v4.new_code_cell(source="\n".join(vcr_import_lines))
|
||||
import_cell.pop("id", None)
|
||||
notebook.cells.insert(0, import_cell)
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
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
|
||||
@@ -1 +0,0 @@
|
||||
eNrtmHlUU1cex1Gs2qKWUpdpa/EZQRRIyL5QdaBhUwxLAFnU4bwkN8kjL++lb2ERmVGsS8Ut2jIq1o6ytYgK1dalFeS4tmqVakctM8o4dhxlXFBH61bnvpAICm5z8BzOkfyTvHt/y/f+fvfe9znJL88EFI2RRI9KjGAAheoZ+EAvyy+nwAcsoJkPy6yAMZOGkrjYhMRilsJO+poZxkYHBwWhNkyAEoyZIm2YXqAnrUGZoiAroGnUBOgSHWnI+bnHnVyeFc1OZ0gLIGheMCISiqWBCM9lBUcm5/IoEgfwF4+lAcWDs3oSSiEYbijLjDJ+NDJKggQgstGIPyIS8/KmchFIA8A5Cz2OsgbAl/BlfJokCMDwcZSBwrlADEnizhwEanXkQA0GbsYAaD2F2bjFcqOhBgONMFkkQrBWHSyIgLPBCBvLpNN6M7Ci0CiXZ4MrBRSDOXTn8loGmRybIzBXPhPUnwc9dR3PcFNcWTEKGDhVMILDmFuPy5jUZQA947BtFW1lcQaz4TkdKNe0TEFNXUz/1LxyM0ANUMziEjNJM/bqdvtlI6rXAxvDB4SeNGCEyb7eNA2zBSIGYOR6WKHn+unYkPYKCwA2PopjmaCsxctehdrguvUoNx+UAXtf6dw3fE5L++kKbnvx4a4jGPuWUJeOoLgcuL0JRCiQSAXiqmw+zaAYgcP9CfcRlFRmc8x/03bChuotMA7feXTsZS3OG9rakLS9VIPqYxMeColSerO9FKWscummtuMUSzCYFdjL1XHt0zknW9NJBCKRQFX9UGA6h9DbS40oToPqB0V+4FIhFoolfKGcLxRtcFUJB4SJMduLZULF5xSgbfDYg1llMCTD0vklsCPg4P5y50FdGxvt6uYptyElYbA79h2JLAhERAokDOgRGF+KiCXBImGwUIxEahIr1c40iR02ozqRQgnaCBsS7mp+ud7MEhZgqFB32PaTvNZlUTA/jlkxhu+8pWCzuEd7iVQoFJ4c+URLCh4HjOAylkhUKtVT4sLKAMa+mVsfXyTmixSJzlUK0zrO4zh1/JYLz6mqjFMFdfk/1b5Vm8tn5DP4PEahOO2kX0feJMu0k1iqdGQLeLp9q0Snj9+z+DxeItKR+yPla0nk8wTLtoVrsUaeaP1YPRXOzvMxg/1b+DtdKJJqU1IUjCxNp9alEtMkBmNaDBYHijMx1F4hEogQE0macLBRHcFXo/Cy5Sc4jpC9PCw1JlQzXl2ZwteSOhLupUQU7jmCJEBZAqDg0bRX6HGSNcDLjgJl0F0bmmrfrDRKUJVMqVDopToDUCn44cnaKtdhenBYSrib0vGOnQmPLAWH9vT4w7CCvm6Oj7shThO9K8TzXsCBKWO28m9V/XhJ8/qgQaFjouomnCD2Srd+qpFs+qr0bG20NqygfN/B3GvNp9644NUP3+q/9Hqzsbrgzq3r/5pWveKXrIaLF9UZAUeQub1zB4kbXgtVvzP9dNVBWYFvj/5FcWv7uP/QkHJm1DBNxNB5cRGpS6eWji+c2XtI1JJeBxuaTV801gwbtnPnvdk3MxbWxM/1HNSnVu3btHKQhzyDVaJnV/r7WhIzTRYy2funSB8/FvEOwsafTznUVBgesJiq+z718tot+f7Jf87Q/eVo7bAPGwv279g4fEHNovClNWcbjkeuGHc4+bP+eeCnmBux6Tvm/8doSy+811cWv3NoXf53ssqdE7dfmuoebZ4/mN8nuFbkuaBh3lnPfuGXZbuHp9Bj1gf4TOeJlq/7buKsTcTC2Zb6G7/Np8Ov7tpiPnB/yryrWyRFmX9XwELev+/u9qdjc3pd6+Hm1klI5L7iRSARRwsuH5SmMXiNE8zDjjAqA7IdIcb74ThiBrgNySFZhCbxTIAwZoxGaAbYEF1OyzdLw20FxwGCZqIYjupwgBhZooUQBVOIKYRIgERgFM0EIjjgNOlRXM9yr27EIS6Y1wYMHLkdOh+MQDpLhwvkrB7BM8cF9wBSJE4kkXEAghlcviw8m1rJB5OiGWVchM5iI7LEpkwmW5MFICI+VJH2VZz8iAx4I0CQeqTSShdDcirTnykxJ5BOBxRFUtDa8TqGWrqBtRtYu4G1s4BVJRZ1LrDKXgpglXR5YJV1fWCVdTFglXUErBIa02barBmoKXSCLSxGqdVOAhHZLxZYVVLUoFM+H7AGtwKrg7UMcXUxu4T97n2yf0jIhPhl9V+cnTOjaTeq8+qblGr5er701a9GyJPuZR3rmf/RMlB77ubdMSENM2YuykzaUNjExp9aP6DguGbUNss7+Hx1r1enL1BWL9l/ydPnep3GPfqY1+TDyBqP/sHCuPeK3j44ONUef8VbdXRbjXbbX5E1A1bXS5af+0fkx83C9Yf3zKgZuO7K8NnqcSPqffdZmci63IFjtVTgDwc8qse+Vtp/wdVk317JviuJIndNXgX13xPjzgtG1qb+/m8ZWvvRQ2MDljRaFZG3M5ffmD6xn9HNo+zjqleKrytropAB1RfqtVfKYyQhv64+crzvXr9zPiW3wo2//rhO+e0aP+Geq2nvW5vGTmIXFzY0rkuI+G3WTXPR/ZSou1lawb7mN1tgNOQcfWZH58HoKz27YfRlg9Hn645YgMSQWa6aurjO0YgWmcgo5WiuSyLx/1Hhtpz4cJmVzjKLxO3rPAlLE1ttLJGcGKcW0yIbw4aGM6JOqrNK/oRCPyZzN/V3U3839b9Q6i8RiZXizsV++UuB/bIuj/3yro/98i6G/fKOsD8+Ki4hCotOAtMiLCajQpqaILaI0ReL/agIAIPqebB/9+02f1Mvio3eFTJwd+33Yr/7OHLy69GC7CuN9UUKe5XPYak0r+hSbsGcI5cF/MEDY92vFb1lrDtS908kL2FSk/DyufOqC6vuXExgqFXj0r0CmdX/XsWzH3kzUDv0cITnW2HuAYEDqovf8L74OypyT8WJgV4rxnskb2eTgvsUyL/0CrjbQL2bdDv4eNCZ5u0jlkVd/XzkH5cXfbJNUTSZNvmbvA+pFx79ZrZ51cqwUN6uWVstUr+9r3sGG88UNqoWF4fXTLnh0Xv1l/K3b+7umX58coF883sZP4eFzt1/6HRYzi8fvX/zsz2Vte8mfxpz2vkXsnf11uUaSO3/Ax5DzIs=
|
||||
@@ -1 +0,0 @@
|
||||
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
|
||||
@@ -1 +0,0 @@
|
||||
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
|
||||
@@ -1 +0,0 @@
|
||||
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
|
||||
@@ -1 +1 @@
|
||||
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
|
||||
@@ -0,0 +1 @@
|
||||
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
|
||||
@@ -0,0 +1 @@
|
||||
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
|
||||
@@ -1 +0,0 @@
|
||||
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
|
||||
@@ -0,0 +1 @@
|
||||
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
|
||||
@@ -1 +0,0 @@
|
||||
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
|
||||
@@ -0,0 +1 @@
|
||||
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
|
||||
@@ -1 +0,0 @@
|
||||
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
|
||||
@@ -1 +0,0 @@
|
||||
eNrtVwlwFFUajkZX14tYulxyNIMFAdKT7jmSmQnRDZOEhBByTA4ChOyb7jeZTvpKd89kBpZDRFglGjugcTfCCrkgAiFARCAIaBEROXZZD4IEI6UIgVUXBFRA9vVkIgmgpVtYpbV2VR+v3//+6/v//71/Xr0XSjIj8LesZngFSoBS0ECumFcvwRIPlJX5dRxU3AJdk57myKr2SEzbaLeiiLItMhKIjF4QIQ8YPSVwkV4yknIDJRJ9iywMsKlxCrT/cKhlpo6DsgwKoayzYVNn6igByeIVNNDloiUjZUxxQ6wUAvSSMIbHZNejughMJwks1Ig8MpR0syKwnit5D8v2IAGyzMgKQFPopyIIbAEFWDYoT/GLASKXhw/Yp9EwtPZHIyrgmEwm0ehNz/BaLaVsfBIbZYeZvnF+jey7JTYknQdcgE8hVAqC2mo0QCr0cEgrTZpu5jQdxSj+aeh7mk52TdPN0s2alX+N8rpkzWjAlgK/jMkenvd3Wd3TaM2IXsYU/BiVrxWU1duxDsBjiRLgKUamBIzprcMw3Q0dei3LnwBZPvrDCTRkA14TFdwk4BzDMxql5lISvWVFgoBDAxdgZagZDDkRRaLikTROhJ4IOuEHwPwxKNFQpiRGDJLpsmWITEAeUAQMUfYwxSVIHNDI9NoyEUiIH0oNOcBclFDISwoDu4Ya1IEPyHs0G6bqeD+lLUNYasZ3K4uMZPhCFAmai1BmMRKkA+QBBj0pBWcRpJDTtaCpd0NAI8nlNW5BVtS1vTOuEVAURD6FPCXQiLu6pnAGI0ZgNHSxQIENCDIeBtyiNhRDKOKAZbywrmuVug6IIstQAUMji2SBXx2EGNc0uX66QUMURznMK+rmONnPU2lIk7jkyHQ/qg88RurN0XrDOh+OgobhWZTvOAuQUnViYH5rzwkRUMWIEx6sPWpd1+K1PWkEWa1NBVSaoxdLIFFutRZIXJRpQ8//kodXGA6q9fb068UFJ6+KM+pJUm9t6sVYs0hdE3jZAk9G2NSLCVQkP04JiJe6nFjb7SwW8oWKW622GEwrJSiLqOrBx+vQMsUjz6tBwMC9u+uD1W9FWko3okdD+tXEI5DUbVluTwRGGrB4SGEGwmBCD5vBYjNZsfGpWavtQTFZN8SkKQulsuxCuCR0x0A95fbwxZBusN8Q/W0a+sgaTX2Uqjj0iYIM8aBW6urJeGZX3ceT4zd0hRouSIWAZ2YExKqrNFBRnWf4jcFplBEaSyQc52S12kxY1wZnuv3dgOwicJLACXKLD0eZDVmGY5DvAs/gRoPgNhLoevV6CkUohrysriLNRNf1Wk8aCXJIG038VU4GK7pabkz1HTeTRmQ1Wbb0ppNhD52qDZz86vXzQR4rCHm1r5sYZ2i17WE0KCBMBAFpA+UyAJeFjKKgiYoGBrMBkpACBhOxWasGFOKioScKkoLLkEJbq+JX2yI44NOyLNZImo1RyNYYVJEo1kNDh8cZL2hGyDGYKEFWAHSjPRG3A8oNcUcg4NT6+LxJcanJ9gYHUtIuCMUMrDh8S2hBAeUqcHKxPorLMHPRLrc1bbyczheUlKbAohxDlsAlp0/MSYnLTvZM8GUbWYXMxsloo4kwmo0GK07qCT2pJ3F7dklWcYrROcMo5lkL7LQ3I9GQmuXmOMt4QhKyxTxTiSkv2eVW3MbJfl+yN40sYl1Mio+l03L14/wZcQqcxLtAnpTF5EJUPaySO0coRNagyhsbGYOhYER1UY4NpgSOUgLvSghzd0LEYHTAB7H63rUwBktCp5I0nvXHYA7NmRC9Ud12MAqMnSTwsG0J8oHHy9CxJYDLTcrMYekSr36CkOAvKSz1O0oJo1fv5YHTYCkyGvMSomdE0+PjejgBRQtOBP0QRZgsgTi8qvr/qNUrk/GeGY6nBbYnhCMvyDzjctU5oISySG2gWMFDo7IuwTqEeWZcnrrR4iKJ6CiLkXRFA8oUbcATcjPXdXP7rh7UaHtCPWBRjHkpdYPbGKuzmUxGXQzGgVhLFIrUwCHtsbquHWrXLSeGLrozJHCFovvKlTJHankVEbbt7JjV1oV3jVtfc+Tw9Jz2qbXei+ofDC6ML+PaHq8I3zOnEfv9s6bn9uxcf3zfTOPZsYNCW//4/LNk2EOTVjSNvpTOV57btKfuYnv5ocHh/m8Gxmy9XMZf+Hb4XtuCUbOrXxpzainxdHbSwRPGiEHS65PMkxYnLIlY/HXDHQMdKzrdzbUieD2xaMD+6q91ZQeJ6fmHHhp++4zdhxrnkq3PXG47tyrliL11RZv54EsXWhJ3L3i4dceAdxPmzoyMLUklHooDpuWfTXl/TeYDc8syNndMePqJAx+WSEP3HZvwyfm8ltlT+iZfvHRm8fYhFSOnbju96cPtEzuX1vZ5RVhZ1Nx/4t867GO3jmnt7z765ZGBoz4cVn/vlhgbtSO/PWrlquLBzxSHVdxXvPu9jpfNL3aMuPzg2C3bU18UJzcve3lRQuVXzBfT/nrY5vgq5u7lFVO+Sf3s2Yuzl6yq3tk8peCOw1XjQ09NpEaN3JDQ/lZrxoycJ0qaRpw4dmvFsLUj/uMfO/OlysqkaecbbREVHc7HP0ka3O+pTbWmB7AX9n5bGl2+8cDZlPwr5ZfuvPOx59ftXfNG5lMfPPmmaWH7nAuNG3d+8hr44o60Qx8/947Zdorefi69rSXcp8t5IfH22+o7+gTgDA1ZdJm+EHpbSMjNPOLfNv23I/7/6RH/Z4NMTKJy7Wan0ZOUMgXk+o1RoivFVzw58xcM2feq/FsjdHMaoaMhYb+1Qr+wVqiOCpwz1bYzv/Bj5s9wALy2DawhSdLy0/rAvj/cB5qJX2kfGGX5lfWBxE3vA60AGCEwAZcrCh3QXbSZMkKnyxhthhbSbCKcP38feBP6i2gLbbXcxP6i6mp/UZaZuugD4sGWi7ktnYP6jTxfwfF31775/MEn9Euc9Mm29xJnpz1HvwLemhMpPXJ6Hf7lijf2VgHXP4p/h5X1jQlrqMy4d//xPjPmvN/vs7cvXD5fubx+9CPN5z8y5g4dun1PYdOEu/hlGbsWdW47tjOvbMHJ+DHlBqeUL7zdEP75nn0Ln+w/uTp1/f5dLcf+TNBnUptWnXFWNX5+oHPZ069j3i+Gh4b4lh5dstj0bd+Y8Jx+9I4weqGzNPbWsGXcuPn37JwfPuqpdyeOrvuLKWHO6funp7cOie0/T6joWFxZMzH9nhFzN0aeCcPK4heWpvQp/3d/ujOuurnwku9euFleViUeb/QV757/2vnwUMddYboYsunNezo+zZrdcnL4i5/u3GU7M2TUgLVvd3488vi+fqf9A+63Tti64+VFna2N7/WvbQLk39Mzz60sPNnSPKj5o9tVfMr21LPRnztke/uVQwfmZ57QdR72v5PYHrXswNi6yK8bN5za4/jT/fcNO5a+aYHty/1V/1rozm83rc+68Co+UB284dFgS7D0n0fSh6B2779lzi3k
|
||||
@@ -1 +1 @@
|
||||
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
|
||||
@@ -1 +1 @@
|
||||
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
|
||||
@@ -1 +1 @@
|
||||
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
|
||||
@@ -1 +1 @@
|
||||
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
|
||||
@@ -1 +0,0 @@
|
||||
eNqNVmtsFFUULqJREoMJz0R+MKxAUXd2Z7ZL220atfQFpS3QWdJCUza3M3d3hs7eO8y903ZtmkjFQJRIJkRjYsBAt7u6KX2EGjTlYYQYmsgf/khVIMbE+EMTjSQkRsA7s7t9F+if7t5zzne+c75zTrYv3QlNomG0ZFBDFJpApuwLsfvSJjxkQUKPpOKQqlhJ7t4lhfstU5vcpFJqkDK/HxiaDyCqmtjQZJ+M4/5O0R+HhIAYJMl2rCR+fOZijycOuiMUd0BEPGWcKASCXs6T92IvrT0eE+uQffJYBJoeZpUxo4Ko89SlAlpIOKpCrgsC9s/kNMSR6JueXi83HQkI0QhlZGaHM2wKu12gHYW6zqlQN7gEtjhZhXLHXFQJIK7GBEjWiIx9DhJNGC68C+ImnHrBWI8wvo4XAnH3LQcVIRCYsupYNGRYTvYej6zRhOMzK4eX2ytVOLgeTcmDWhFBrEkYAYV2ldS2N9cXt6jbVKlREls8vW2zap7frdY5/ExILH1OSzyShVBig1tdrobIU2V3WJIINE1sMu8o0AlkhNocMbECdQdB1oGlQL6I38oTjBCkvA4om6F8spzci/dLgUQ2NcMZQZeqa+Ci2Jwp1VRjI4TJGAdufw02hNCkmjtSU+2e7gehpoZinl6n2c5kayZ0im7NerbN0Bq3H4QyU5sVl1YhUNh6nEiqmFB7dN7ADwNZhgblIZKxwvDtc7G3NcPLKTDqVJ6RnS64G2VnOiA0eKBrnTCVjbJHgGHomgwcu/8g69hgTibe4TLfnHEU59naIGpfqMjz8O9OsP1EnOArCvoCI9082wMN6WzBWPcZpZTh2sdnGgwgdzAcPrf7diobPDTTBxN7oAHIu6RZkI4g9gAw48XB8zPfTQtRLQ7tdOXu+elyxul0RT5R9IVGZwGTBJLtAXeuRqeaPBWSCQiBIl4o5gVxKN8lHaIYVe3+EkH4nI26we4WfDfFIKlF+pJMEfj99XTu0pzdtTOv5p2Ctckqpo59qRkqXk4UuSoocww/yImlZYJQJga52obwYGUuTXhBMUbDbItJlAlSnRc/LasW6oBKpnJB2Sc902WZLL+uxTXK584sE8v5aieDgiBMbn6sp8mGXkNOxmRRKBR6Ai7rDKT2mFMfLwZ4UQznqizav3Aed7f47MXOsUo5rBiv157oP80tH7P5KWIWYRjcP1m4UDS26DyKA6Vuttef7D9NMRdT+DQxi1PkFgqf075soo2P8ZzZuKw391jvRflkcsrzmmJfZJ/ZRa9orK1Vw1rXwdD+urpY4yEFVVcF6vs7NWBnRJ/IxTCO6XC4soavBOyk8pK7Qna6al9jRcOOysEWvgm3YzZLYcBmDmEEUxI02WraGVnHlsKOnQlTLLypYp89VhoVSrZGS9rF0kBIiBYH+ermppH8Mk0tS9K5lO6PhMOp7HG+9mD9By8UuH9L60/cqLv61qr3IrB8XcnK7e2rT8GKtUOrzqyzhQbfxK2JU2X3P/zy48vjY1u+Kvvr1PrS548sWX7+eNvt8uHiw90H7pZ0PPz59tDdzy43//OKl14ZkN6v+m/7yPVXT7+zdtnZ06vXkJe3fHvmxOUXw217f/hoY/Rm5txP1dIF3vvvtbpBY/jolT0Dw9ID7/Kd/uAn12oKA9veuH9yYuOmTMvKe03HV/12aZl+oPzTo398/dLNwpNXS7/4ZWz8m79vbAvGx+sPrLh6uPv3MeW74Q339hzr6ft1RX916K75/LN31vwZjB97Dh2SWpNnH+0jXeUPWZ2PHi0t2Hyrd2LrkoKC/wFNFp9z
|
||||
@@ -1 +1 @@
|
||||
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
|
||||
@@ -0,0 +1 @@
|
||||
eNqNVX1sE2UY3xgkOiAQVFSUcDYogrvu2l63dcboKGwO2IdrHYxl1Ld3b9tj17vj3ve6DkLCV4JR+Tid8vGHICutlAqbbqAyTAbRQSCIxIhDlIQ/FELUEUKIRjPfu7X7Fu0/vXvf5+P3/H7P89ymRASqSJCl7JQgYagCDpMXpG9KqHCNBhHeEg9DHJL5WHWVx9uqqULv0yGMFVScnw8UwQokHFJlReCsnBzOj9jywxAhEIQo5pf55is5U9ZZwiDqw3IjlJClmLIxdjaPsmSsyEn9Oosqi5A8WTQEVQu55WQCRcLGUVMI4HmIwiFINUFA/lRKkCgUeNGyPo8a8gQICQgTMCPdSWwMo2Ygr0wFIR4VKCCrYWAUTJEnygMkqlQFEicgTs6jyimOHBBMw518CAKVC1EBTTKZslLLSNQwpAIQk2NM4I6J2yxrVgMXblZMsCYkE/7giSyLPpLJsJJA2DwbmdC4ESRFM2pZZ+EE3GzYjEL8qqfEiGsR+ExQzcfY6rx8nX+h2x6pq8OFfjfkAjjkbLKsbxjB4Fju60fhUyHSxFEEWzyaJDU/ZVaXrsH3v7IbKJEPqqqsEusAEBEkgBqM1pB5KBoROBFoPKQdtJNGsiRBTNtJ8zAFdiaTLt0+/84YDxGnCoqhhAk2rR3RZJikg9T6EBeCYWAyrJCmhioWzBYdJHyIEYRVQQpa1ht0G5MiqNAou37AsmGY2rJ/NeSI3qS8RAgCnozbjlhIRlhvHzNARwHHQQXTUOJknsTXPwquFZQ8iocBEWCY5AwezL7Tk40QKjQQhQiMD3jpbUBRRIEzGy9/NeEslRaKNrCMvU4amtNkDCWsHy/J4MivbibzLlGM1cFa7W1RmsyVIIlkYGkREEhxxbw/MfxCAVwjiUOnd4keH3A+MtxGRvrBCsBVeUaENATRDwI1XMB+Mvxc1SQshKGecFePTZe+HErnsNpsVlf7iMCoWeL0g2ZntQ+SPOiSJL3koJkCmrEdybAkQimIQ3prYRHzIWl2hexBuDlOQmINbYoRReD5M4n05jpQtTSj5k9ZM2KLiDr6SW9Iy6PsBZQHKpTRq5TNUewoKLY7qLIKb8qdTuMdV4x2L5ljFCCCLM6In+BCmtQI+aR7XNl7LUNlqSS/KIQFTKfXNhHLeNVjLMMwvc/c11IlTS9IRsaYw+Vy/UdcwgzEeodRH824aHuBd6BKJ7uylxrPc2D3p/HEDTwE0dz7WA7hyVhT97UeH4/dsTKZBk0LvN5Fnsk6WuYvjIZKK/2SVBtdGaldoYJFTtvazijNibLG05h8ACFtNkQU670Uy7N8EWPjgJ9leSfJUcAGGMj7eQY4bX4H1xoRgJ60WW1UUJaDIjzqLqXdgKwR2mO2jZ5YVFdZUlHuTq2ga2S/TPjzAsKzJEsw7oEqaUc9aaYmA67COHGvKanTO4o4lwOwhUU8LHJwLOukFy+vacs00GCDxIztYH5oN8YHFtKX2ZVz3nwgy/zleKu7l+S8MuWvd3cvza8/1El/+mhJd01f7cXNL5dfi/9Y5nvnz7eDDUv6G449e2P+aT7w2M9b2rtn3TvWsE1atWpX07mqfZ7vnaee3P71nZ6K7tyTzytH/Y4r9trdzrsT9yxGM3py711RTs1yH7jU1xcpmr33jbZpPa23efaJHW2n9l/P2373h5uF3/5x+Livcts0/uqG3Oi515a5Onb2LlEPW6/qZ+svTJ/03ty+lvKFHfunT029jpe39W3M7t57KHq1ZeJU7eQXx7femJ06MXmVp2nq5FtrAtTNrm0fT6r86qLwOLvz+vbuRyIHyvZ3zuy/XIJ+n/D3/I5vuubtWNC24aUJdMI9Z2LPjV9feP/ac+zl0wsce3K/O3Mp1cV379t6uww8+FZnS8uCvF2dtx4qdT3s++y3FVNuncW1H8zsP1fR88udQkJcf39O1ucX2Mbz2VlZ/wBwZ4U6
|
||||
@@ -1 +1 @@
|
||||
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
|
||||
@@ -1 +1 @@
|
||||
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
|
||||
@@ -1 +1 @@
|
||||
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
|
||||
@@ -1 +1 @@
|
||||
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
|
||||
@@ -0,0 +1,216 @@
|
||||
# API Concepts
|
||||
|
||||
This page describes the high-level concepts of the LangGraph Cloud API. The conceptual guide of LangGraph (Python library) is [here](../../concepts/high_level.md).
|
||||
|
||||
## Data Models
|
||||
|
||||
The LangGraph Cloud API consists of a few core data models: [Assistants](#assistants), [Threads](#threads), [Runs](#runs), and [Cron Jobs](#cron-jobs).
|
||||
|
||||
### Assistants
|
||||
|
||||
When building agents, it is fairly common to make rapid changes that *do not* alter the graph logic. For example, simply changing prompts or the LLM selection can have significant impacts on the behavior of the agents. Assistants offer an easy way to make and save these types of changes to agent configuration. This can have at least two use-cases:
|
||||
|
||||
* Assistants give developers a quick and easy way to modify and version graph version for experimentation.
|
||||
* Assistants can be modified via LangGraph Studio, offering a no-code way to configure agents (e.g., for business users).
|
||||
|
||||
#### Configuring Assistants
|
||||
|
||||
In practice, an assistant is just an *instance* of a graph with a specific configuration. Because of this, multiple assistants can reference the same graph but can contain different configurations, such as prompts, models, and other graph configuration options. The LangGraph Cloud API provides several endpoints for creating and managing assistants. See the [API reference](../reference/api/api_ref.html#tag/assistantscreate) and [this how-to](../how-tos/configuration_cloud.md) for more details on how to create assistants.
|
||||
|
||||
#### Versioning Assistants
|
||||
|
||||

|
||||
|
||||
Once you've created an assistant, you can save and version it to track changes to the configuration over time. You can think about this at three levels:
|
||||
|
||||
1) The graph lays out the general agent application logic
|
||||
2) The agent configuration options represent parameters that can be changed
|
||||
3) Assistant versions save and track specific settings of the agent configuration options
|
||||
|
||||
For example, if you have an agent that helps for planning trips, you can create a new assistant *for each user* that passes specific user preferences (e.g., desired airline and car service). As each user interacts with their own assistant, assistant versions can be saved that track the specific desires of the user. Read [this how-to](../how-tos/assistant_versioning.md) to learn how you can use assistant versioning through both the [Studio](../how-tos/index.md/#langgraph-studio) and the SDK.
|
||||
|
||||
### Threads
|
||||
|
||||
A thread contains the accumulated state of a group of runs. If a run is executed on a thread, then the [state][state] of the underlying graph of the assistant will be persisted to the thread. A thread's current and historical state can be retrieved. To persist state, a thread must be created prior to executing a run.
|
||||
|
||||
The state of a thread at a particular point in time is called a checkpoint.
|
||||
|
||||
For more on threads and checkpoints, see this section of the [LangGraph conceptual guide](../../concepts/low_level.md#persistence).
|
||||
|
||||
The LangGraph Cloud API provides several endpoints for creating and managing threads and thread state. See the [API reference](../reference/api/api_ref.html#tag/threadscreate) for more details.
|
||||
|
||||
### Runs
|
||||
|
||||
A run is an invocation of an assistant. Each run may have its own input, configuration, and metadata, which may affect execution and output of the underlying graph. A run can optionally be executed on a thread.
|
||||
|
||||
The LangGraph Cloud API provides several endpoints for creating and managing runs. See the [API reference](../reference/api/api_ref.html#tag/runscreate) for more details.
|
||||
|
||||
### Cron Jobs
|
||||
|
||||
It's often useful to run graphs on some schedule. LangGraph Cloud supports cron jobs, which run on a user defined schedule. The user specifies a schedule, an assistant, and some input. After than, on the specified schedule LangGraph cloud will:
|
||||
|
||||
- Create a new thread with the specified assistant
|
||||
- Send the specified input to that thread
|
||||
|
||||
Note that this sends the same input to the thread every time. See the [how-to guide](../how-tos/cron_jobs.md) for creating cron jobs.
|
||||
|
||||
The LangGraph Cloud API provides several endpoints for creating and managing cron jobs. See the [API reference](../reference/api/api_ref.html#tag/runscreate/POST/threads/{thread_id}/runs/crons) for more details.
|
||||
|
||||
## Features
|
||||
|
||||
The LangGraph Cloud API offers several features to support complex agent architectures.
|
||||
|
||||
### Streaming
|
||||
|
||||
Streaming is critical for making LLM applications feel responsive to end users. When creating a streaming run, the streaming mode determines what data is streamed back to the API client. The LangGraph Cloud API supports five streaming modes.
|
||||
|
||||
- `values`: Stream the full state of the graph after each [super-step](https://langchain-ai.github.io/langgraph/concepts/low_level/#graphs) is executed. See the [how-to guide](../how-tos/stream_values.md) for streaming values.
|
||||
- `messages`: Stream complete messages (at the end of node execution) as well as tokens for any messages generated inside a node. This mode is primarily meant for powering chat applications. This is only an option if your graph contains a `messages` key. See the [how-to guide](../how-tos/stream_messages.md) for streaming messages.
|
||||
- `updates`: Streams updates to the state of the graph after each node is executed. See the [how-to guide](../how-tos/stream_updates.md) for streaming updates.
|
||||
- `events`: Stream all events (including the state of the graph) that occur during graph execution. See the [how-to guide](../how-tos/stream_events.md) for streaming events. This can be used to do token-by-token streaming for LLMs.
|
||||
- `debug`: Stream debug events throughout graph execution. See the [how-to guide](../how-tos/stream_debug.md) for streaming debug events.
|
||||
|
||||
You can also specify multiple streaming modes at the same time. See the [how-to guide](../how-tos/stream_multiple.md) for configuring multiple streaming modes at the same time.
|
||||
|
||||
See the [API reference](../reference/api/api_ref.html#tag/runscreate/POST/threads/{thread_id}/runs/stream) for how to create streaming runs.
|
||||
|
||||
Streaming modes `values`, `updates`, and `debug` are very similar to modes available in the LangGraph library - for a deeper conceptual explanation of those, you can see the LangGraph library documentation [here](../../concepts/low_level.md#streaming).
|
||||
|
||||
Streaming mode `events` is the same as using `.astream_events` in the LangGraph library - for a deeper conceptual explanation of this, you can see the LangGraph library documentation [here](../../concepts/low_level.md#streaming).
|
||||
|
||||
#### `mode="messages"`
|
||||
Streaming mode `messages` is a new streaming mode, currently only available in the API. What does this mode enable?
|
||||
|
||||
This mode is focused on streaming back messages. It currently assumes that you have a `messages` key in your graph that is a list of messages. Assuming we have a simple react agent deployed, what does this stream look like?
|
||||
|
||||
All events emitted have two attributes:
|
||||
|
||||
- `event`: This is the name of the event
|
||||
- `data`: This is data associated with the event
|
||||
|
||||
Let's run it on a question that should trigger a tool call:
|
||||
|
||||
```python
|
||||
thread = await client.threads.create()
|
||||
input = {"messages": [{"role": "user", "content": "what's the weather in sf?"}]}
|
||||
|
||||
events = []
|
||||
async for event in client.runs.stream(
|
||||
thread["thread_id"],
|
||||
assistant_id="agent", # This may need to change depending on the graph you deployed
|
||||
input=input,
|
||||
stream_mode="messages",
|
||||
):
|
||||
print(event.event)
|
||||
```
|
||||
```shell
|
||||
metadata
|
||||
messages/complete
|
||||
messages/metadata
|
||||
messages/partial
|
||||
...
|
||||
messages/partial
|
||||
messages/complete
|
||||
messages/complete
|
||||
messages/metadata
|
||||
messages/partial
|
||||
...
|
||||
messages/partial
|
||||
messages/complete
|
||||
end
|
||||
```
|
||||
|
||||
We first get some `metadata` - this is metadata about the run.
|
||||
|
||||
```python
|
||||
StreamPart(event='metadata', data={'run_id': '1ef657cf-ae55-6f65-97d4-f4ed1dbdabc6'})
|
||||
```
|
||||
|
||||
We then get a `messages/complete` event - this a fully formed message getting emitted. In this case,
|
||||
this was the just the input message we sent in.
|
||||
|
||||
```python
|
||||
StreamPart(event='messages/complete', data=[{'content': 'hi!', 'additional_kwargs': {}, 'response_metadata': {}, 'type': 'human', 'name': None, 'id': '833c09a3-bb19-46c9-81d9-1e5954ec5f92', 'example': False}])
|
||||
```
|
||||
|
||||
We then get a `messages/metadata` - this is just letting us know that a new message is starting.
|
||||
|
||||
```python
|
||||
StreamPart(event='messages/metadata', data={'run-985c0f14-9f43-40d4-a505-4637fc58e333': {'metadata': {'created_by': 'system', 'run_id': '1ef657de-7594-66df-8eb2-31518e4a1ee2', 'graph_id': 'agent', 'thread_id': 'c178eab5-e293-423c-8e7d-1d113ffe7cd9', 'model_name': 'openai', 'assistant_id': 'fe096781-5601-53d2-b2f6-0d3403f7e9ca', 'langgraph_step': 1, 'langgraph_node': 'agent', 'langgraph_triggers': ['start:agent'], 'langgraph_task_idx': 0, 'ls_provider': 'openai', 'ls_model_name': 'gpt-4o', 'ls_model_type': 'chat', 'ls_temperature': 0.0}}})
|
||||
```
|
||||
|
||||
We then get a BUNCH of `messages/partial` events - these are the individual tokens from the LLM! In the case below, we can see the START of a tool call.
|
||||
|
||||
```python
|
||||
StreamPart(event='messages/partial', data=[{'content': '', 'additional_kwargs': {'tool_calls': [{'index': 0, 'id': 'call_w8Hr8dHGuZCPgRfd5FqRBArs', 'function': {'arguments': '', 'name': 'tavily_search_results_json'}, 'type': 'function'}]}, 'response_metadata': {}, 'type': 'ai', 'name': None, 'id': 'run-985c0f14-9f43-40d4-a505-4637fc58e333', 'example': False, 'tool_calls': [], 'invalid_tool_calls': [{'name': 'tavily_search_results_json', 'args': '', 'id': 'call_w8Hr8dHGuZCPgRfd5FqRBArs', 'error': None}], 'usage_metadata': None}])
|
||||
```
|
||||
|
||||
After that, we get a `messages/complete` event - this is the AIMessage finishing. It's now a complete tool call:
|
||||
|
||||
```python
|
||||
StreamPart(event='messages/complete', data=[{'content': '', 'additional_kwargs': {'tool_calls': [{'index': 0, 'id': 'call_w8Hr8dHGuZCPgRfd5FqRBArs', 'function': {'arguments': '{"query":"current weather in San Francisco"}', 'name': 'tavily_search_results_json'}, 'type': 'function'}]}, 'response_metadata': {'finish_reason': 'tool_calls', 'model_name': 'gpt-4o-2024-05-13', 'system_fingerprint': 'fp_157b3831f5'}, 'type': 'ai', 'name': None, 'id': 'run-985c0f14-9f43-40d4-a505-4637fc58e333', 'example': False, 'tool_calls': [{'name': 'tavily_search_results_json', 'args': {'query': 'current weather in San Francisco'}, 'id': 'call_w8Hr8dHGuZCPgRfd5FqRBArs'}], 'invalid_tool_calls': [], 'usage_metadata': None}])
|
||||
```
|
||||
|
||||
After that, we get ANOTHER `messages/complete` event. This is a tool message - our agent has called a tool, gotten a response, and now inserting it into the state in the form of a tool message.
|
||||
|
||||
```python
|
||||
StreamPart(event='messages/complete', data=[{'content': '[{"url": "https://www.weatherapi.com/", "content": "{\'location\': {\'name\': \'San Francisco\', \'region\': \'California\', \'country\': \'United States of America\', \'lat\': 37.78, \'lon\': -122.42, \'tz_id\': \'America/Los_Angeles\', \'localtime_epoch\': 1724877689, \'localtime\': \'2024-08-28 13:41\'}, \'current\': {\'last_updated_epoch\': 1724877000, \'last_updated\': \'2024-08-28 13:30\', \'temp_c\': 23.3, \'temp_f\': 73.9, \'is_day\': 1, \'condition\': {\'text\': \'Partly cloudy\', \'icon\': \'//cdn.weatherapi.com/weather/64x64/day/116.png\', \'code\': 1003}, \'wind_mph\': 15.0, \'wind_kph\': 24.1, \'wind_degree\': 310, \'wind_dir\': \'NW\', \'pressure_mb\': 1014.0, \'pressure_in\': 29.93, \'precip_mm\': 0.0, \'precip_in\': 0.0, \'humidity\': 57, \'cloud\': 25, \'feelslike_c\': 25.0, \'feelslike_f\': 77.1, \'windchill_c\': 20.9, \'windchill_f\': 69.6, \'heatindex_c\': 23.3, \'heatindex_f\': 74.0, \'dewpoint_c\': 12.9, \'dewpoint_f\': 55.2, \'vis_km\': 16.0, \'vis_miles\': 9.0, \'uv\': 6.0, \'gust_mph\': 19.5, \'gust_kph\': 31.3}}"}]', 'additional_kwargs': {}, 'response_metadata': {}, 'type': 'tool', 'name': 'tavily_search_results_json', 'id': '0112eba5-7660-4375-9f24-c7a1d6777b97', 'tool_call_id': 'call_w8Hr8dHGuZCPgRfd5FqRBArs'}])
|
||||
```
|
||||
|
||||
After that, we see the agent doing another LLM call and streaming back a response. We then get an `end` event:
|
||||
|
||||
```python
|
||||
StreamPart(event='end', data=None)
|
||||
```
|
||||
|
||||
And that's it! This is more focused streaming mode specifically focused on streaming back messages. See this [how-to guide](../how-tos/stream_messages.md) for more information.
|
||||
|
||||
|
||||
### Human-in-the-Loop
|
||||
|
||||
There are many occasions where the graph cannot run completely autonomously. For instance, the user might need to input some additional arguments to a function call, or select the next edge for the graph to continue on. In these instances, we need to insert some human in the loop interaction, which you can learn about in the [human in the loop how-tos](../how-tos/index.md#human-in-the-loop).
|
||||
|
||||
### Double Texting
|
||||
|
||||
Many times users might interact with your graph in unintended ways. For instance, a user may send one message and before the graph has finished running send a second message. To solve this issue of "double-texting" (i.e. prompting the graph a second time before the first run has finished), LangGraph has provided four different solutions, all of which are covered in the [Double Texting how-tos](../how-tos/index.md#double-texting). These options are:
|
||||
|
||||
- `reject`: This is the simplest option, this just rejects any follow up runs and does not allow double texting. See the [how-to guide](../how-tos/reject_concurrent.md) for configuring the reject double text option.
|
||||
- `enqueue`: This is a relatively simple option which continues the first run until it completes the whole run, then sends the new input as a separate run. See the [how-to guide](../how-tos/enqueue_concurrent.md) for configuring the enqueue double text option.
|
||||
- `interrupt`: This option interrupts the current execution but saves all the work done up until that point. It then inserts the user input and continues from there. If you enable this option, your graph should be able to handle weird edge cases that may arise. See the [how-to guide](../how-tos/interrupt_concurrent.md) for configuring the interrupt double text option.
|
||||
- `rollback`: This option rolls back all work done up until that point. It then sends the user input in, basically as if it just followed the original run input. See the [how-to guide](../how-tos/rollback_concurrent.md) for configuring the rollback double text option.
|
||||
|
||||
### Stateless Runs
|
||||
|
||||
All runs use the built-in checkpointer to store checkpoints for runs. However, it can often be useful to just kick off a run without worrying about explicitly creating a thread and without wanting to keep those checkpointers around. Stateless runs allow you to do this by exposing an endpoint that:
|
||||
|
||||
- Takes in user input
|
||||
- Under the hood, creates a thread
|
||||
- Runs the agent but skips all checkpointing steps
|
||||
- Cleans up the thread afterwards
|
||||
|
||||
Stateless runs are still retried as regular retries are per node, while everything still in memory, so doesn't use checkpoints.
|
||||
|
||||
The only difference is in stateless background runs, if the task worker dies halfway (not because the run itself failed, for some external reason) then the whole run will be retried like any background run, but
|
||||
|
||||
- whereas a stateful background run would retry from the last successful checkpoint
|
||||
- a stateless background run would retry from the beginning
|
||||
|
||||
See the [how-to guide](../how-tos/stateless_runs.md) for creating stateless runs.
|
||||
|
||||
### Webhooks
|
||||
|
||||
For all types of runs, langgraph cloud supports completion webhooks. When you create the run you can pass a webhook URL to be called when the completes (successfully or not). This is especially useful for background runs and cron jobs, as the webhook can give you an indication the run has completed and you can perform further actions for your appilcation.
|
||||
|
||||
See this [how-to guide](../how-tos/webhooks.md) to learn about how to use webhooks with LangGraph Cloud.
|
||||
|
||||
## Deployment
|
||||
|
||||
The LangGraph Cloud offers several features to support secure and robost deployments.
|
||||
|
||||
### Authentication
|
||||
|
||||
LangGraph applications deployed to LangGraph Cloud are automatically configured with LangSmith authentication. In order to call the API, a valid <a href="https://docs.smith.langchain.com/how_to_guides/setup/create_account_api_key#api-keys" target="_blank">LangSmith API key</a> is required.
|
||||
|
||||
### Local Testing
|
||||
|
||||
Before deploying your app in production to LangGraph Cloud, you may wish to test out your graph locally in order to ensure that everything is running as expected. Luckily, LangGraph makes this easy for you through use of the LangGraph CLI. Read more in this [how-to guide](../deployment/test_locally.md) or look at the [CLI reference](../reference/cli.md) to learn more.
|
||||
|
After Width: | Height: | Size: 257 KiB |
@@ -0,0 +1,28 @@
|
||||
# Cloud Concepts
|
||||
|
||||
This page describes the high-level concepts of the LangGraph Cloud deployment.
|
||||
|
||||
## Deployment
|
||||
|
||||
A deployment is an instance of a LangGraph API. A single deployment can have many [revisions](#revision). When a deployment is created, all of the necessary infrastructure (e.g. database, containers, secrets store) are automatically provisioned. See the [architecture diagram](#architecture) below for more details.
|
||||
|
||||
See the [how-to guide](../deployment/cloud.md#create-new-deployment) for creating a new deployment.
|
||||
|
||||
## Revision
|
||||
|
||||
A revision is an iteration of a [deployment](#deployment). When a new deployment is created, an initial revision is automatically created. To deploy new code changes or update environment variable configurations for a deployment, a new revision must be created. When a revision is created, a new container image is built automatically.
|
||||
|
||||
See the [how-to guide](../deployment/cloud.md#create-new-revision) for creating a new revision.
|
||||
|
||||
## Asynchronous Deployment
|
||||
|
||||
Infrastructure for [deployments](#deployment) and [revisions](#revision) are provisioned and deployed asynchronously. They are not deployed immediately after submission. Currently, deployment can take up to several minutes.
|
||||
|
||||
## Architecture
|
||||
|
||||
!!! warning "Subject to Change"
|
||||
The LangGraph Cloud deployment architecture may change in the future.
|
||||
|
||||
A high-level diagram of a LangGraph Cloud deployment.
|
||||
|
||||

|
||||
|
Before Width: | Height: | Size: 157 KiB After Width: | Height: | Size: 157 KiB |
@@ -5,17 +5,17 @@ LangGraph Cloud is available within <a href="https://www.langchain.com/langsmith
|
||||
## Prerequisites
|
||||
|
||||
1. LangGraph Cloud applications are deployed from GitHub repositories. Configure and upload a LangGraph Cloud application to a GitHub repository in order to deploy it to LangGraph Cloud.
|
||||
1. [Verify that the LangGraph API runs locally](test_locally.md). If the API does not run successfully (i.e. `langgraph dev`), deploying to LangGraph Cloud will fail as well.
|
||||
1. [Verify that the LangGraph API runs locally](test_locally.md). If the API does not build and run successfully (i.e. `langgraph up`), deploying to LangGraph Cloud will fail as well.
|
||||
|
||||
## Create New Deployment
|
||||
|
||||
Starting from the <a href="https://smith.langchain.com/" target="_blank">LangSmith UI</a>...
|
||||
|
||||
1. In the left-hand navigation panel, select `LangGraph Platform`. The `LangGraph Platform` view contains a list of existing LangGraph Cloud deployments.
|
||||
1. In the left-hand navigation panel, select `Deployments`. The `Deployments` view contains a list of existing LangGraph Cloud deployments.
|
||||
1. In the top-right corner, select `+ New Deployment` to create a new deployment.
|
||||
1. In the `Create New Deployment` panel, fill out the required fields.
|
||||
1. `Deployment details`
|
||||
1. Select `Import from GitHub` and follow the GitHub OAuth workflow to install and authorize LangChain's `hosted-langserve` GitHub app to access the selected repositories. After installation is complete, return to the `Create New Deployment` panel and select the GitHub repository to deploy from the dropdown menu. **Note**: The GitHub user installing LangChain's `hosted-langserve` GitHub app must be an [owner](https://docs.github.com/en/organizations/managing-peoples-access-to-your-organization-with-roles/roles-in-an-organization#organization-owners) of the organization or account.
|
||||
1. Select `Import from GitHub` and follow the GitHub OAuth workflow to install and authorize LangChain's `hosted-langserve` GitHub app to access the selected repositories. After installation is complete, return to the `Create New Deployment` panel and select the GitHub repository to deploy from the dropdown menu.
|
||||
1. Specify a name for the deployment.
|
||||
1. Specify the desired `Git Branch`. A deployment is linked to a branch. When a new revision is created, code for the linked branch will be deployed. The branch can be updated later in the [Deployment Settings](#deployment-settings).
|
||||
1. Specify the full path to the [LangGraph API config file](../reference/cli.md#configuration-file) including the file name. For example, if the file `langgraph.json` is in the root of the repository, simply specify `langgraph.json`.
|
||||
@@ -38,7 +38,7 @@ When [creating a new deployment](#create-new-deployment), a new revision is crea
|
||||
|
||||
Starting from the <a href="https://smith.langchain.com/" target="_blank">LangSmith UI</a>...
|
||||
|
||||
1. In the left-hand navigation panel, select `LangGraph Platform`. The `LangGraph Platform` view contains a list of existing LangGraph Cloud deployments.
|
||||
1. In the left-hand navigation panel, select `Deployments`. The `Deployments` view contains a list of existing LangGraph Cloud deployments.
|
||||
1. Select an existing deployment to create a new revision for.
|
||||
1. In the `Deployment` view, in the top-right corner, select `+ New Revision`.
|
||||
1. In the `New Revision` modal, fill out the required fields.
|
||||
@@ -52,15 +52,15 @@ Starting from the <a href="https://smith.langchain.com/" target="_blank">LangSmi
|
||||
1. Update the value of existing secrets or environment variables.
|
||||
1. Select `Submit`. After a few seconds, the `New Revision` modal will close and the new revision will be queued for deployment.
|
||||
|
||||
## View Build and Server Logs
|
||||
## View Build and Deployment Logs
|
||||
|
||||
Build and server logs are available for each revision.
|
||||
Build and deployment logs are available for each revision.
|
||||
|
||||
Starting from the `LangGraph Platform` view...
|
||||
Starting from the `Deployment` view...
|
||||
|
||||
1. Select the desired revision from the `Revisions` table. A panel slides open from the right-hand side and the `Build` tab is selected by default, which displays build logs for the revision.
|
||||
1. In the panel, select the `Server` tab to view server logs for the revision. Server logs are only available after a revision has been deployed.
|
||||
1. Within the `Server` tab, adjust the date/time range picker as needed. By default, the date/time range picker is set to the `Last 7 days`.
|
||||
1. In the panel, select the `Deploy` tab to view deployment logs for the revision.
|
||||
1. Within the `Deploy` tab, adjust the date/time range picker as needed. By default, the date/time range picker is set to the `Last 15 minutes`.
|
||||
|
||||
## Interrupt Revision
|
||||
|
||||
@@ -69,7 +69,7 @@ Interrupting a revision will stop deployment of the revision.
|
||||
!!! warning "Undefined Behavior"
|
||||
Interrupted revisions have undefined behavior. This is only useful if you need to deploy a new revision and you already have a revision "stuck" in progress. In the future, this feature may be removed.
|
||||
|
||||
Starting from the `LangGraph Platform` view...
|
||||
Starting from the `Deployment` view...
|
||||
|
||||
1. Select the menu icon (three dots) on the right-hand side of the row for the desired revision from the `Revisions` table.
|
||||
1. Select `Interrupt` from the menu.
|
||||
@@ -79,13 +79,13 @@ Starting from the `LangGraph Platform` view...
|
||||
|
||||
Starting from the <a href="https://smith.langchain.com/" target="_blank">LangSmith UI</a>...
|
||||
|
||||
1. In the left-hand navigation panel, select `LangGraph Platform`. The `LangGraph Platform` view contains a list of existing LangGraph Cloud deployments.
|
||||
1. In the left-hand navigation panel, select `Deployments`. The `Deployments` view contains a list of existing LangGraph Cloud deployments.
|
||||
1. Select the menu icon (three dots) on the right-hand side of the row for the desired deployment and select `Delete`.
|
||||
1. A `Confirmation` modal will appear. Select `Delete`.
|
||||
|
||||
## Deployment Settings
|
||||
|
||||
Starting from the `LangGraph Platform` view...
|
||||
Starting from the `Deployment` view...
|
||||
|
||||
1. In the top-right corner, select the gear icon (`Deployment Settings`).
|
||||
1. Update the `Git Branch` to the desired branch.
|
||||
|
||||
|
Before Width: | Height: | Size: 736 KiB |
|
Before Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 304 KiB |
|
Before Width: | Height: | Size: 266 KiB |
|
Before Width: | Height: | Size: 376 KiB |
|
Before Width: | Height: | Size: 400 KiB |
|
Before Width: | Height: | Size: 461 KiB |
|
Before Width: | Height: | Size: 642 KiB |
|
After Width: | Height: | Size: 124 KiB |
|
Before Width: | Height: | Size: 288 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 418 KiB After Width: | Height: | Size: 128 KiB |
|
Before Width: | Height: | Size: 401 KiB After Width: | Height: | Size: 95 KiB |
|
Before Width: | Height: | Size: 453 KiB After Width: | Height: | Size: 131 KiB |
|
After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 514 KiB |
@@ -1,123 +0,0 @@
|
||||
# How to add semantic search to your LangGraph deployment
|
||||
|
||||
This guide explains how to add semantic search to your LangGraph deployment's cross-thread [store](../../concepts/persistence.md#memory-store), so that your agent can search for memories and other documents by semantic similarity.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- A LangGraph deployment (see [how to deploy](setup_pyproject.md))
|
||||
- API keys for your embedding provider (in this case, OpenAI)
|
||||
- `langchain >= 0.3.8` (if you specify using the string format below)
|
||||
|
||||
## Steps
|
||||
|
||||
1. Update your `langgraph.json` configuration file to include the store configuration:
|
||||
|
||||
```json
|
||||
{
|
||||
...
|
||||
"store": {
|
||||
"index": {
|
||||
"embed": "openai:text-embeddings-3-small",
|
||||
"dims": 1536,
|
||||
"fields": ["$"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This configuration:
|
||||
|
||||
- Uses OpenAI's text-embeddings-3-small model for generating embeddings
|
||||
- Sets the embedding dimension to 1536 (matching the model's output)
|
||||
- Indexes all fields in your stored data (`["$"]` means index everything, or specify specific fields like `["text", "metadata.title"]`)
|
||||
|
||||
2. To use the string embedding format above, make sure your dependencies include `langchain >= 0.3.8`:
|
||||
|
||||
```toml
|
||||
# In pyproject.toml
|
||||
[project]
|
||||
dependencies = [
|
||||
"langchain>=0.3.8"
|
||||
]
|
||||
```
|
||||
|
||||
Or if using requirements.txt:
|
||||
|
||||
```
|
||||
langchain>=0.3.8
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Once configured, you can use semantic search in your LangGraph nodes. The store requires a namespace tuple to organize memories:
|
||||
|
||||
```python
|
||||
def search_memory(state: State, *, store: BaseStore):
|
||||
# Search the store using semantic similarity
|
||||
# The namespace tuple helps organize different types of memories
|
||||
# e.g., ("user_facts", "preferences") or ("conversation", "summaries")
|
||||
results = store.search(
|
||||
namespace=("memory", "facts"), # Organize memories by type
|
||||
query="your search query",
|
||||
limit=3 # number of results to return
|
||||
)
|
||||
return results
|
||||
```
|
||||
|
||||
## Custom Embeddings
|
||||
|
||||
If you want to use custom embeddings, you can pass a path to a custom embedding function:
|
||||
|
||||
```json
|
||||
{
|
||||
...
|
||||
"store": {
|
||||
"index": {
|
||||
"embed": "path/to/embedding_function.py:embed",
|
||||
"dims": 1536,
|
||||
"fields": ["$"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The deployment will look for the function in the specified path. The function must be async and accept a list of strings:
|
||||
|
||||
```python
|
||||
# path/to/embedding_function.py
|
||||
from openai import AsyncOpenAI
|
||||
|
||||
client = AsyncOpenAI()
|
||||
|
||||
async def aembed_texts(texts: list[str]) -> list[list[float]]:
|
||||
"""Custom embedding function that must:
|
||||
1. Be async
|
||||
2. Accept a list of strings
|
||||
3. Return a list of float arrays (embeddings)
|
||||
"""
|
||||
response = await client.embeddings.create(
|
||||
model="text-embedding-3-small",
|
||||
input=texts
|
||||
)
|
||||
return [e.embedding for e in response.data]
|
||||
```
|
||||
|
||||
## Querying via the API
|
||||
|
||||
You can also query the store using the LangGraph SDK. Since the SDK uses async operations:
|
||||
|
||||
```python
|
||||
from langgraph_sdk import get_client
|
||||
|
||||
async def search_store():
|
||||
client = get_client()
|
||||
results = await client.store.search_items(
|
||||
("memory", "facts"),
|
||||
query="your search query",
|
||||
limit=3 # number of results to return
|
||||
)
|
||||
return results
|
||||
|
||||
# Use in an async context
|
||||
results = await search_store()
|
||||
```
|
||||
@@ -36,8 +36,8 @@ Dependencies can optionally be specified in one of the following files: `pyproje
|
||||
The dependencies below will be included in the image, you can also use them in your code, as long as with a compatible version range:
|
||||
|
||||
```
|
||||
langgraph>=0.2.56,<0.3.0
|
||||
langgraph-checkpoint>=2.0.5,<3.0
|
||||
langgraph>=0.2.30,<0.3.0
|
||||
langgraph-checkpoint>=1.0.14
|
||||
langchain-core>=0.2.38,<0.4.0
|
||||
langsmith>=0.1.63
|
||||
orjson>=3.9.7
|
||||
|
||||