Compare commits

...
Author SHA1 Message Date
William FHandGitHub ff1370a9a5 Release CLI (#2465) 2024-11-19 08:41:18 +00:00
William FHandGitHub 679a7365da Add default ns in put_writes (#2404) 2024-11-18 22:55:12 -08:00
b2522ffe19 CLI Dev command (#2463)
Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
2024-11-19 05:12:03 +00:00
Eugene YurtsevandGitHub 4212a795a0 docs[minor]: Fix layout issues in available templates (#2452) 2024-11-18 22:53:19 -05:00
Eugene YurtsevandGitHub 517d67aa32 docs: Update to use LANGSMITH_API_KEY throughout (#2461) 2024-11-18 22:51:36 -05:00
Brace SproulandGitHub feaf14765a Merge pull request #2458 from langchain-ai/brace/expose-command-interface
fix(sdk-js): Expose Command interface
2024-11-18 18:54:19 -08:00
Vadym BardaandGitHub cc6063c729 docs: simplify multi-agent tutorials (#2443) 2024-11-19 02:31:12 +00:00
013397042e docs: grammar (#2449)
Co-authored-by: Ian Sullivan <ian@frame.ai>
2024-11-18 21:01:37 -05:00
Nuno Campos 9a775d9c9f 0.2.52 2024-11-18 17:17:40 -08:00
Nuno Campos 2c945ceb68 Copy configurable in ensure_config 2024-11-18 17:17:20 -08:00
Erick FriisandGitHub 39eabd0fb8 Merge pull request #2459 from langchain-ai/erick/docs-self-hosted-plan-links
docs: self-hosted plan links
2024-11-18 16:42:02 -08:00
Erick Friis e5cc2e2044 docs: self-hosted plan links 2024-11-18 16:35:19 -08:00
bracesproul f00c0515e7 add jsdoc 2024-11-18 16:32:32 -08:00
bracesproul d87c0d4d53 fix(sdk-js): Expose Command interface 2024-11-18 16:25:51 -08:00
Nuno Campos fb40a974c8 0.2.51 2024-11-18 16:03:04 -08:00
Nuno Campos d63bfc6879 Add missing property 2024-11-18 16:02:54 -08:00
Nuno CamposandGitHub 97dd30711a Merge pull request #2437 from langchain-ai/nc/16nov/speed-up-find-subgraph
lib: find_subgraph doesn't need to look in both func and afunc
2024-11-18 15:59:58 -08:00
Nuno Campos 7866bd2718 lib: find_subgraph doesn't need to look in both func and afunc
- if they both exist they're expected to share the same implementation, so looking in both is redundant
2024-11-16 16:57:32 -08:00
28 changed files with 2066 additions and 933 deletions
@@ -39,7 +39,6 @@ NOTEBOOKS_NO_EXECUTION = [
# 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/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
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+6 -6
View File
@@ -21,7 +21,7 @@ Install the proper packages:
Ensure you have an API key, which you can create from the [LangSmith UI](https://smith.langchain.com) (Settings > API Keys). This is required to authenticate that you have LangGraph Cloud access. After you have saved the key to a safe place, place the following line in your `.env` file:
```python
LANGCHAIN_API_KEY = *********
LANGSMITH_API_KEY = *********
```
## Start the API server
@@ -54,7 +54,7 @@ You can either initialize by passing authentication or by setting an environment
from langgraph_sdk import get_client
# only pass the url argument to get_client() if you changed the default port when calling langgraph up
client = get_client(url=<DEPLOYMENT_URL>,api_key=<LANGCHAIN_API_KEY>)
client = get_client(url=<DEPLOYMENT_URL>,api_key=<LANGSMITH_API_KEY>)
# Using the graph deployed with the name "agent"
assistant_id = "agent"
thread = await client.threads.create()
@@ -66,7 +66,7 @@ You can either initialize by passing authentication or by setting an environment
import { Client } from "@langchain/langgraph-sdk";
// only set the apiUrl if you changed the default port when calling langgraph up
const client = new Client({ apiUrl: <DEPLOYMENT_URL>, apiKey: <LANGCHAIN_API_KEY> });
const client = new Client({ apiUrl: <DEPLOYMENT_URL>, apiKey: <LANGSMITH_API_KEY> });
// Using the graph deployed with the name "agent"
const assistantId = "agent";
const thread = await client.threads.create();
@@ -78,13 +78,13 @@ You can either initialize by passing authentication or by setting an environment
curl --request POST \
--url <DEPLOYMENT_URL>/threads \
--header 'Content-Type: application/json'
--header 'x-api-key: <LANGCHAIN_API_KEY>'
--header 'x-api-key: <LANGSMITH_API_KEY>'
```
#### Initialize with environment variables
If you have a `LANGCHAIN_API_KEY` set in your environment, you do not need to explicitly pass authentication to the client
If you have a `LANGSMITH_API_KEY` set in your environment, you do not need to explicitly pass authentication to the client
=== "Python"
@@ -154,7 +154,7 @@ Now we can invoke our graph to ensure it is working. Make sure to change the inp
}
```
=== "CURL"
=== "CURL"
```bash
curl --request POST \
+2 -2
View File
@@ -2,13 +2,13 @@
LLMs are extremely powerful, particularly when connected to other systems such as a retriever or APIs. This is why many LLM applications use a control flow of steps before and / or after LLM calls. As an example [RAG](https://github.com/langchain-ai/rag-from-scratch) performs retrieval of relevant documents to a question, and passes those documents to an LLM in order to ground the response. Often a control flow of steps before and / or after an LLM is called a "chain." Chains are a popular paradigm for programming with LLMs and offer a high degree of reliability; the same set of steps runs with each chain invocation.
However, we often want LLM systems that can pick their own control flow! This is one definition of an [agent](https://blog.langchain.dev/what-is-an-agent/): an agent is a system that uses an LLM to decide the control flow of an application. Unlike a chain, an agent given an LLM some degree of control over the sequence of steps in the application. Examples of using an LLM to decide the control of an application:
However, we often want LLM systems that can pick their own control flow! This is one definition of an [agent](https://blog.langchain.dev/what-is-an-agent/): an agent is a system that uses an LLM to decide the control flow of an application. Unlike a chain, an agent gives an LLM some degree of control over the sequence of steps in the application. Examples of using an LLM to decide the control of an application:
- Using an LLM to route between two potential paths
- Using an LLM to decide which of many tools to call
- Using an LLM to decide whether the generated answer is sufficient or more work is need
There are many different types of [agent architectures](https://blog.langchain.dev/what-is-a-cognitive-architecture/) to consider, which given an LLM varying levels of control. On one extreme, a router allows an LLM to select a single step from a specified set of options and, on the other extreme, a fully autonomous long-running agent may have complete freedom to select any sequence of steps that it wants for a given problem.
There are many different types of [agent architectures](https://blog.langchain.dev/what-is-a-cognitive-architecture/) to consider, which give an LLM varying levels of control. On one extreme, a router allows an LLM to select a single step from a specified set of options and, on the other extreme, a fully autonomous long-running agent may have complete freedom to select any sequence of steps that it wants for a given problem.
![Agent Types](img/agent_types.png)
+8 -16
View File
@@ -6,22 +6,14 @@
Templates are open source reference applications designed to help you get started quickly when building with LangGraph. They provide working examples of common agentic workflows that can be customized to your needs.
Templates can be accessed via [LangGraph Studio](langgraph_studio.md), or cloned directly from Github. You can download LangGraph Studio and see available templates [here](https://studio.langchain.com/).
Templates can be accessed via [LangGraph Studio (macOS only)](langgraph_studio.md), or cloned directly from Github. You can download LangGraph Studio and see available templates [here](https://studio.langchain.com/).
## Available templates
- **New LangGraph Project**: A simple, minimal chatbot with memory.
- [Python](https://github.com/langchain-ai/new-langgraph-project)
- [JS/TS](https://github.com/langchain-ai/new-langgraphjs-project)
- **ReAct Agent**: A simple agent that can be flexibly extended to many tools.
- [Python](https://github.com/langchain-ai/react-agent)
- [JS/TS](https://github.com/langchain-ai/react-agent-js)
- **Memory Agent**: A ReAct-style agent with an additional tool to store memories for use across conversational threads.
- [Python](https://github.com/langchain-ai/memory-agent)
- [JS/TS](https://github.com/langchain-ai/memory-agent-js)
- **Retrieval Agent**: An agent that includes a retrieval-based question-answering system.
- [Python](https://github.com/langchain-ai/retrieval-agent-template)
- [JS/TS](https://github.com/langchain-ai/retrieval-agent-template-js)
- **Data-enrichment Agent**: An agent that performs web searches and organizes its findings into a structured format.
- [Python](https://github.com/langchain-ai/data-enrichment)
- [JS/TS](https://github.com/langchain-ai/data-enrichment-js)
| Template | Description | Python | JS/TS |
|---------------------------|------------------------------------------------------------------------------------------|------------------------------------------------------------------|---------------------------------------------------------------------|
| **New LangGraph Project** | A simple, minimal chatbot with memory. | [Repo](https://github.com/langchain-ai/new-langgraph-project) | [Repo](https://github.com/langchain-ai/new-langgraphjs-project) |
| **ReAct Agent** | A simple agent that can be flexibly extended to many tools. | [Repo](https://github.com/langchain-ai/react-agent) | [Repo](https://github.com/langchain-ai/react-agent-js) |
| **Memory Agent** | A ReAct-style agent with an additional tool to store memories for use across threads. | [Repo](https://github.com/langchain-ai/memory-agent) | [Repo](https://github.com/langchain-ai/memory-agent-js) |
| **Retrieval Agent** | An agent that includes a retrieval-based question-answering system. | [Repo](https://github.com/langchain-ai/retrieval-agent-template) | [Repo](https://github.com/langchain-ai/retrieval-agent-template-js) |
| **Data-Enrichment Agent** | An agent that performs web searches and organizes its findings into a structured format. | [Repo](https://github.com/langchain-ai/data-enrichment) | [Repo](https://github.com/langchain-ai/data-enrichment-js) |
+3 -3
View File
@@ -23,8 +23,8 @@ You will eventually need to pass in the following environment variables to the L
- `REDIS_URI`: Connection details to a Redis instance. Redis will be used as a pub-sub broker to enable streaming real time output from background runs.
- `DATABASE_URI`: Postgres connection details. Postgres will be used to store assistants, threads, runs, persist thread state and long term memory, and to manage the state of the background task queue with 'exactly once' semantics.
- `LANGSMITH_API_KEY`: (If using [Self-Hosted Lite]) LangSmith API key. This will be used to authenticate ONCE at server start up.
- `LANGGRAPH_CLOUD_LICENSE_KEY`: (If using Self-Hosted Enterprise) LangGraph Platform license key. This will be used to authenticate ONCE at server start up.
- `LANGSMITH_API_KEY`: (If using [Self-Hosted Lite](../concepts/deployment_options.md#self-hosted-lite)) LangSmith API key. This will be used to authenticate ONCE at server start up.
- `LANGGRAPH_CLOUD_LICENSE_KEY`: (If using [Self-Hosted Enterprise](../concepts/deployment_options.md#self-hosted-enterprise)) LangGraph Platform license key. This will be used to authenticate ONCE at server start up.
## Build the Docker Image
@@ -70,7 +70,7 @@ If you want to run this quickly without setting up a separate Redis and Postgres
* You need to replace `my-image` with the name of the image you built in the previous step (from `langgraph build`).
and you should provide appropriate values for `REDIS_URI`, `DATABASE_URI`, and `LANGSMITH_API_KEY`.
* If your application requires additional environment variables, you can pass them in a similar way.
* If using Self-Hosted Enterprise, you must provide `LANGGRAPH_CLOUD_LICENSE_KEY` as an additional environment variable.
* If using [Self-Hosted Enterprise](../concepts/deployment_options.md#self-hosted-enterprise), you must provide `LANGGRAPH_CLOUD_LICENSE_KEY` as an additional environment variable.
### Using Docker Compose
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -112,7 +112,7 @@
"metadata": {},
"outputs": [],
"source": [
"_set_env(\"LANGCHAIN_API_KEY\")\n",
"_set_env(\"LANGSMITH_API_KEY\")\n",
"os.environ[\"LANGCHAIN_TRACING_V2\"] = \"true\"\n",
"os.environ[\"LANGCHAIN_PROJECT\"] = \"local-llama32-rag\""
]
@@ -372,7 +372,7 @@ class MemorySaver(
RunnableConfig: The updated config containing the saved writes' timestamp.
"""
thread_id = config["configurable"]["thread_id"]
checkpoint_ns = config["configurable"]["checkpoint_ns"]
checkpoint_ns = config["configurable"].get("checkpoint_ns", "")
checkpoint_id = config["configurable"]["checkpoint_id"]
outer_key = (thread_id, checkpoint_ns, checkpoint_id)
outer_writes_ = self.writes.get(outer_key)
+103 -8
View File
@@ -1,10 +1,105 @@
# langchain-cli
# LangGraph CLI
This package implements the official CLI for LangGraph API.
The official command-line interface for LangGraph, providing tools to create, develop, and deploy LangGraph applications.
## How to Test CLI Changes Locally
These instructions are for CLI development and testing. Use the CLI examples to test CLI changes locally.
1. Make changes to the CLI code.
1. Navigate to the `libs/cli/examples`: `cd libs/cli/examples`
1. Install CLI examples dependencies: `poetry install`
1. Run/test CLI command (e.g. `langgraph build`).
## Installation
Install via pip:
```bash
pip install langgraph-cli
```
For development mode with hot reloading:
```bash
pip install "langgraph-cli[inmem]"
```
## Commands
### `langgraph new` 🌱
Create a new LangGraph project from a template
```bash
langgraph new [PATH] --template TEMPLATE_NAME
```
### `langgraph dev` 🏃‍♀️
Run LangGraph API server in development mode with hot reloading
```bash
langgraph dev [OPTIONS]
--host TEXT Host to bind to (default: 127.0.0.1)
--port INTEGER Port to bind to (default: 2024)
--no-reload Disable auto-reload
--debug-port INTEGER Enable remote debugging
--no-browser Skip opening browser window
-c, --config FILE Config file path (default: langgraph.json)
```
### `langgraph up` 🚀
Launch LangGraph API server in Docker
```bash
langgraph up [OPTIONS]
-p, --port INTEGER Port to expose (default: 8123)
--wait Wait for services to start
--watch Restart on file changes
--verbose Show detailed logs
-c, --config FILE Config file path
-d, --docker-compose Additional services file
```
### `langgraph build`
Build a Docker image for your LangGraph application
```bash
langgraph build -t IMAGE_TAG [OPTIONS]
--platform TEXT Target platforms (e.g., linux/amd64,linux/arm64)
--pull / --no-pull Use latest/local base image
-c, --config FILE Config file path
```
### `langgraph dockerfile`
Generate a Dockerfile for custom deployments
```bash
langgraph dockerfile SAVE_PATH [OPTIONS]
-c, --config FILE Config file path
```
## Configuration
The CLI uses a `langgraph.json` configuration file with these key settings:
```json
{
"dependencies": ["langchain_openai", "./your_package"], // Required: Package dependencies
"graphs": {
"my_graph": "./your_package/file.py:graph" // Required: Graph definitions
},
"env": "./.env", // Optional: Environment variables
"python_version": "3.11", // Optional: Python version (3.11/3.12)
"pip_config_file": "./pip.conf", // Optional: pip configuration
"dockerfile_lines": [] // Optional: Additional Dockerfile commands
}
```
See the [full documentation](https://langchain-ai.github.io/langgraph/docs/cloud/reference/cli.html) for detailed configuration options.
## Development
To develop the CLI itself:
1. Clone the repository
2. Navigate to the CLI directory: `cd libs/cli`
3. Install development dependencies: `poetry install`
4. Make your changes to the CLI code
5. Test your changes:
```bash
# Run CLI commands directly
poetry run langgraph --help
# Or use the examples
cd examples
poetry install
poetry run langgraph dev # or other commands
```
## License
This project is licensed under the terms specified in the repository's LICENSE file.
+111 -12
View File
@@ -285,9 +285,11 @@ def _build(
subp_exec(
"docker",
"pull",
f"{base_image}:{config_json['node_version']}"
if config_json.get("node_version")
else f"{base_image}:{config_json['python_version']}",
(
f"{base_image}:{config_json['node_version']}"
if config_json.get("node_version")
else f"{base_image}:{config_json['python_version']}"
),
verbose=True,
)
)
@@ -443,9 +445,11 @@ def dockerfile(save_path: str, config: pathlib.Path, add_docker_compose: bool) -
langgraph_cli.config.config_to_docker(
config,
config_json,
"langchain/langgraphjs-api"
if config_json.get("node_version")
else "langchain/langgraph-api",
(
"langchain/langgraphjs-api"
if config_json.get("node_version")
else "langchain/langgraph-api"
),
)
)
secho("✅ Created: Dockerfile", fg="green")
@@ -523,6 +527,97 @@ def new(path: Optional[str], template: Optional[str]) -> None:
return create_new(path, template)
@click.option(
"--host",
default="127.0.0.1",
help="Network interface to bind the development server to. Default 127.0.0.1 is recommended for security. Only use 0.0.0.0 in trusted networks",
)
@click.option(
"--port",
default=2024,
type=int,
help="Port number to bind the development server to. Example: langgraph dev --port 8000",
)
@click.option(
"--no-reload",
is_flag=True,
help="Disable automatic reloading when code changes are detected",
)
@click.option(
"--config",
type=click.Path(exists=True),
default="langgraph.json",
help="Path to configuration file declaring dependencies, graphs and environment variables",
)
@click.option(
"--n-jobs-per-worker",
default=None,
type=int,
help="Maximum number of concurrent jobs each worker process can handle. Default: 10",
)
@click.option(
"--no-browser",
is_flag=True,
help="Skip automatically opening the browser when the server starts",
)
@click.option(
"--debug-port",
default=None,
type=int,
help="Enable remote debugging by listening on specified port. Requires debugpy to be installed",
)
@cli.command(
"dev",
help="🏃‍♀️‍➡️ Run LangGraph API server in development mode with hot reloading and debugging support",
)
@log_command
def dev(
host: str,
port: int,
no_reload: bool,
config: str,
n_jobs_per_worker: Optional[int],
no_browser: bool,
debug_port: Optional[int],
):
"""CLI entrypoint for running the LangGraph API server."""
try:
from langgraph_api.cli import run_server
except ImportError:
try:
import pkg_resources
pkg_resources.require("langgraph-api-inmem")
except (ImportError, pkg_resources.DistributionNotFound):
raise click.UsageError(
"Required package 'langgraph-api-inmem' is not installed.\n"
"Please install it with:\n\n"
' pip install -U "langgraph-cli[inmem]"\n\n'
"If you're developing the langgraph-cli package locally, you can install in development mode:\n"
" pip install -e ."
) from None
raise click.UsageError(
"Could not import run_server. This likely means your installation is incomplete.\n"
"Please ensure langgraph-cli is installed with the 'inmem' extra: pip install -U \"langgraph-cli[inmem]\""
) from None
import json
with open(config, encoding="utf-8") as f:
config_data = json.load(f)
graphs = config_data.get("graphs", {})
run_server(
host,
port,
not no_reload,
graphs,
n_jobs_per_worker=n_jobs_per_worker,
open_browser=not no_browser,
debug_port=debug_port,
)
def prepare_args_and_stdin(
*,
capabilities: DockerCapabilities,
@@ -556,9 +651,11 @@ def prepare_args_and_stdin(
config_path,
config,
watch=watch,
base_image="langchain/langgraphjs-api"
if config.get("node_version")
else "langchain/langgraph-api",
base_image=(
"langchain/langgraphjs-api"
if config.get("node_version")
else "langchain/langgraph-api"
),
)
return args, stdin
@@ -585,9 +682,11 @@ def prepare(
subp_exec(
"docker",
"pull",
f"langchain/langgraphjs-api:{config['node_version']}"
if config.get("node_version")
else f"langchain/langgraph-api:{config['python_version']}",
(
f"langchain/langgraphjs-api:{config['node_version']}"
if config.get("node_version")
else f"langchain/langgraph-api:{config['python_version']}"
),
verbose=verbose,
)
)
+1252 -2
View File
File diff suppressed because it is too large Load Diff
+5 -1
View File
@@ -1,6 +1,6 @@
[tool.poetry]
name = "langgraph-cli"
version = "0.1.54"
version = "0.1.55"
description = "CLI for interacting with LangGraph API"
authors = []
license = "MIT"
@@ -14,6 +14,7 @@ langgraph = "langgraph_cli.cli:cli"
[tool.poetry.dependencies]
python = "^3.9.0,<4.0"
click = "^8.1.7"
langgraph-api-inmem = { version = ">=0.0.3,<0.1.0", optional = true }
[tool.poetry.group.dev.dependencies]
ruff = "^0.6.2"
@@ -24,6 +25,9 @@ pytest-mock = "^3.11.1"
pytest-watch = "^4.2.0"
mypy = "^1.10.0"
[tool.poetry.extras]
inmem = ["langgraph-api-inmem"]
[tool.pytest.ini_options]
# --strict-markers will raise errors on unknown marks.
# https://docs.pytest.org/en/7.1.x/how-to/mark.html#raising-errors-on-unknown-marks
+8
View File
@@ -191,6 +191,14 @@ def map_debug_checkpoint(
"state": t.state,
}
if t.error
else {
"id": t.id,
"name": t.name,
"result": t.result,
"interrupts": tuple(asdict(i) for i in t.interrupts),
"state": t.state,
}
if t.result
else {
"id": t.id,
"name": t.name,
+1 -1
View File
@@ -48,7 +48,7 @@ def find_subgraph_pregel(candidate: Runnable) -> Optional[Runnable]:
nl.__self__ if hasattr(nl, "__self__") else nl
for nl in get_function_nonlocals(c.func)
)
if c.afunc is not None:
elif c.afunc is not None:
candidates.extend(
nl.__self__ if hasattr(nl, "__self__") else nl
for nl in get_function_nonlocals(c.afunc)
+4 -1
View File
@@ -280,7 +280,10 @@ def ensure_config(*configs: Optional[RunnableConfig]) -> RunnableConfig:
continue
for k, v in config.items():
if v is not None and k in CONFIG_KEYS:
empty[k] = v # type: ignore[literal-required]
if k == CONF:
empty[k] = v.copy() # type: ignore[literal-required]
else:
empty[k] = v # type: ignore[literal-required]
for k, v in config.items():
if v is not None and k not in CONFIG_KEYS:
empty[CONF][k] = v
+1 -1
View File
@@ -1,6 +1,6 @@
[tool.poetry]
name = "langgraph"
version = "0.2.50"
version = "0.2.52"
description = "Building stateful, multi-actor applications with LLMs"
authors = []
license = "MIT"
+1 -1
View File
@@ -17,4 +17,4 @@ export type {
Checkpoint,
} from "./schema.js";
export type { OnConflictBehavior } from "./types.js";
export type { OnConflictBehavior, Command } from "./types.js";
+9
View File
@@ -29,10 +29,19 @@ export interface Send {
}
export interface Command {
/**
* An object to update the thread state with.
*/
update?: Record<string, unknown>;
/**
* The value to return from an `interrupt` function call.
*/
resume?: unknown;
/**
* A single, or array of `Send` commands to trigger nodes.
*/
send?: Send | Send[];
}