diff --git a/.github/workflows/deploy_docs.yml b/.github/workflows/deploy_docs.yml index 6a18593e4..179d8f845 100644 --- a/.github/workflows/deploy_docs.yml +++ b/.github/workflows/deploy_docs.yml @@ -1,4 +1,4 @@ -name: Deploy SDK Docs +name: Deploy Docs on: push: @@ -36,7 +36,6 @@ jobs: poetry run pip install -r docs/docs-requirements.txt - name: Build site - working-directory: ./docs run: make build-docs - name: Configure GitHub Pages diff --git a/Makefile b/Makefile index 3b36cef84..e779fc3ac 100644 --- a/Makefile +++ b/Makefile @@ -51,7 +51,7 @@ spell_fix: build-docs: poetry run python docs/_scripts/copy_notebooks.py - poetry run mkdocs build --clean -f docs/mkdocs.yml + poetry run mkdocs build --clean -f docs/mkdocs.yml --strict serve-docs: build-docs poetry run mkdocs serve -f docs/mkdocs.yml diff --git a/README.md b/README.md index 16f301cd3..ec0923eac 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ [![Downloads](https://static.pepy.tech/badge/langgraph/month)](https://pepy.tech/project/langgraph) [![Open Issues](https://img.shields.io/github/issues-raw/langchain-ai/langgraph)](https://github.com/langchain-ai/langgraph/issues) [![](https://dcbadge.vercel.app/api/server/6adMQxSpJS?compact=true&style=flat)](https://discord.com/channels/1038097195422978059/1170024642245832774) +[![Docs](https://img.shields.io/badge/docs-latest-blue)](https://langchain-ai.github.io/langgraph/) ⚡ Building language agents as graphs ⚡ @@ -524,92 +525,7 @@ content='' additional_kwargs={'function_call': {'arguments': '{\n', 'name': ''}} content='' additional_kwargs={'function_call': {'arguments': ' ', 'name': ''}} content='' additional_kwargs={'function_call': {'arguments': ' "', 'name': ''}} content='' additional_kwargs={'function_call': {'arguments': 'query', 'name': ''}} -content='' additional_kwargs={'function_call': {'arguments': '":', 'name': ''}} -content='' additional_kwargs={'function_call': {'arguments': ' "', 'name': ''}} -content='' additional_kwargs={'function_call': {'arguments': 'weather', 'name': ''}} -content='' additional_kwargs={'function_call': {'arguments': ' in', 'name': ''}} -content='' additional_kwargs={'function_call': {'arguments': ' San', 'name': ''}} -content='' additional_kwargs={'function_call': {'arguments': ' Francisco', 'name': ''}} -content='' additional_kwargs={'function_call': {'arguments': '"\n', 'name': ''}} -content='' additional_kwargs={'function_call': {'arguments': '}', 'name': ''}} -content='' -content='' -content='I' -content="'m" -content=' sorry' -content=',' -content=' but' -content=' I' -content=' couldn' -content="'t" -content=' find' -content=' the' -content=' current' -content=' weather' -content=' in' -content=' San' -content=' Francisco' -content='.' -content=' However' -content=',' -content=' you' -content=' can' -content=' check' -content=' the' -content=' historical' -content=' weather' -content=' data' -content=' for' -content=' January' -content=' ' -content='202' -content='4' -content=' in' -content=' San' -content=' Francisco' -content=' [' -content='here' -content='](' -content='https' -content='://' -content='we' -content='athers' -content='park' -content='.com' -content='/h' -content='/m' -content='/' -content='557' -content='/' -content='202' -content='4' -content='/' -content='1' -content='/H' -content='istorical' -content='-' -content='Weather' -content='-in' -content='-Jan' -content='uary' -content='-' -content='202' -content='4' -content='-in' -content='-S' -content='an' -content='-F' -content='r' -content='anc' -content='isco' -content='-Cal' -content='ifornia' -content='-' -content='United' -content='-' -content='States' -content=').' -content='' +... ``` ## When to Use diff --git a/docs/_scripts/copy_notebooks.py b/docs/_scripts/copy_notebooks.py index 4ebad26d9..f7c414f13 100644 --- a/docs/_scripts/copy_notebooks.py +++ b/docs/_scripts/copy_notebooks.py @@ -9,7 +9,33 @@ docs_dir = root_dir / "docs/docs" how_tos_dir = docs_dir / "how-tos" tutorials_dir = docs_dir / "tutorials" +_MANUAL = { + "how-tos": [ + "async.ipynb", + "streaming-tokens.ipynb", + "human-in-the-loop.ipynb", + "persistence.ipynb", + "time-travel.ipynb", + "visualization.ipynb", + "state-model.ipynb", + "subgraph.ipynb", + "persistence_postgres.ipynb", + "branching.ipynb", + ], + "tutorials": [ + "chat_agent_executor_with_function_calling/base.ipynb", + "chat_agent_executor_with_function_calling/high-level.ipynb", + "chat_agent_executor_with_function_calling/high-level-tools.ipynb", + "chat_agent_executor_with_function_calling/prebuilt-tool-node.ipynb", + "agent_executor/base.ipynb", + "agent_executor/high-level.ipynb", + ], +} +_MANUAL_INVERSE = {v: docs_dir / k for k, vs in _MANUAL.items() for v in vs} _HOW_TOS = {"agent_executor", "chat_agent_executor_with_function_calling", "docs"} +_MAP = { + "persistence_postgres.ipynb": "tutorial", +} _IGNORE = (".ipynb_checkpoints", ".venv", ".cache") @@ -33,30 +59,48 @@ def clean_notebooks(): def copy_notebooks(): # Nested ones are mostly tutorials rn for root, dirs, files in os.walk(examples_dir): - if root == str(examples_dir): - continue - if any(path.startswith(".") or path.startswith("__") for path in root.split(os.sep)): + if any( + path.startswith(".") or path.startswith("__") for path in root.split(os.sep) + ): continue if any(path in _HOW_TOS for path in root.split(os.sep)): dst_dir = how_tos_dir else: dst_dir = tutorials_dir for file in files: - if file.endswith(".ipynb"): + dst_dir_ = dst_dir + if file.endswith((".ipynb", ".png")): + if file in _MAP: + dst_dir = os.path.join(dst_dir, _MAP[file]) src_path = os.path.join(root, file) dst_path = os.path.join( dst_dir, os.path.relpath(src_path, examples_dir) ) + for k in _MANUAL_INVERSE: + if src_path.endswith(k): + overridden_dir = _MANUAL_INVERSE[k] + dst_path = os.path.join(overridden_dir, os.path.relpath(src_path, examples_dir)) + print(f"Overriding {src_path} to {dst_path}") + break + os.makedirs(os.path.dirname(dst_path), exist_ok=True) shutil.copy(src_path, dst_path) + # Convert all ./img/* to ../img/* + if file.endswith(".ipynb"): + with open(dst_path, "r") as f: + content = f.read() + content = content.replace("(./img/", "(../img/") + with open(dst_path, "w") as f: + f.write(content) + dst_dir = dst_dir_ # Top level notebooks are "how-to's" - for file in examples_dir.iterdir(): - if file.suffix.endswith(".ipynb") and not os.path.isdir( - os.path.join(examples_dir, file) - ): - src_path = os.path.join(examples_dir, file) - dst_path = os.path.join(docs_dir, "how-tos", file.name) - shutil.copy(src_path, dst_path) + # for file in examples_dir.iterdir(): + # if file.suffix.endswith(".ipynb") and not os.path.isdir( + # os.path.join(examples_dir, file) + # ): + # src_path = os.path.join(examples_dir, file) + # dst_path = os.path.join(docs_dir, "how-tos", file.name) + # shutil.copy(src_path, dst_path) if __name__ == "__main__": diff --git a/docs/docs/concepts.md b/docs/docs/concepts.md deleted file mode 100644 index fb5732b9c..000000000 --- a/docs/docs/concepts.md +++ /dev/null @@ -1,4 +0,0 @@ -# Concepts - - -## State \ No newline at end of file diff --git a/docs/docs/how-tos/index.md b/docs/docs/how-tos/index.md index 1e11de709..12d8c5200 100644 --- a/docs/docs/how-tos/index.md +++ b/docs/docs/how-tos/index.md @@ -2,24 +2,29 @@ Welcome to the LangGraph How-To Guides! These guides provide practical, step-by-step instructions for accomplishing key tasks in LangGraph. -## Basics - -- [State Management](state-model.ipynb): How to define and manage complex state in your graphs -- [Tool Integration](sql_example.ipynb): How to integrate external tools and data sources -- [Human-in-the-Loop](human-in-the-loop.ipynb): How to incorporate human feedback and intervention - -## Performance +## Core - [Async Execution](async.ipynb): How to run nodes asynchronously for improved performance - [Streaming Responses](streaming-tokens.ipynb): How to stream agent responses in real-time - -## Graph Structure - -- [Subgraphs](subgraph.ipynb): How to modularize your graphs with subgraphs +- [Human-in-the-Loop](human-in-the-loop.ipynb): How to incorporate human feedback and intervention +- [Persistence](persistence.ipynb): How to save and load graph state for long-running applications +- [Time Travel](time-travel.ipynb): How to navigate and manipulate graph state history +- [Visualization](visualization.ipynb): How to visualize your graphs +- [Pydantic State](state-model.ipynb): Use a pydantic model as your state +- [Subgraphs](subgraph.ipynb): How to compose subgraphs within a larger graph - [Branching](branching.ipynb): How to create branching logic in your graphs -## Development +## AgentExecutor + +- [Human-in-the-Loop](agent_executor/human-in-the-loop.ipynb) +- [Force Tool First](agent_executor/force-calling-a-tool-first.ipynb) +- [Manage Agent Steps](agent_executor/managing-agent-steps.ipynb) + +## Chat Agent (Function Calling) + +- [Human-in-the-Loop](chat_agent_executor_with_function_calling/human-in-the-loop.ipynb) +- [Force Tool First](chat_agent_executor_with_function_calling/force-calling-a-tool-first.ipynb) +- [Respond in Format](chat_agent_executor_with_function_calling/respond-in-format.ipynb) +- [Dynamic Direct Return](chat_agent_executor_with_function_calling/dynamically-returning-directly.ipynb) +- [Manage Agent Steps](chat_agent_executor_with_function_calling/managing-agent-steps.ipynb) -- [Persistence](persistence.ipynb): How to save and load graph state for long-running applications -- [Visualization](visualization.ipynb): How to visualize your graphs -- [Time Travel](time-travel.ipynb): How to navigate and manipulate graph execution history \ No newline at end of file diff --git a/docs/docs/index.md b/docs/docs/index.md index 77e9dcb39..3ef70d025 100644 --- a/docs/docs/index.md +++ b/docs/docs/index.md @@ -4,119 +4,111 @@ ⚡ Build language agents as graphs ⚡ - ## Overview -Suppose you're building a customer support assistant. You want your assistant to: +Suppose you're building a customer support assistant. You want your assistant to be able to: -1. Try to answer user questions using a knowledge base -2. Escalate to a human if it's not confident in its answer -3. Relay the human's resolution back to the user -4. Remember the full conversation context across multiple user messages +1. Use tools to respond to questions +2. Connect with a human if needed +3. Be able to pause the process indefinitely and resume whenever the human responds -With raw LLMs, the code to control the agentic loop, conversation state, route between the chatbot and human, and checkpoint the full application state can get complex. +LangGraph makes this all easy. First install: -LangGraph makes it simple. First install: - -```shell +```bash pip install -U langgraph ``` Then define your assistant: ```python -from langgraph.graph import StateGraph +import json + +from langchain_anthropic import ChatAnthropic +from langchain_community.tools.tavily_search import TavilySearchResults + from langgraph.checkpoint.sqlite import SqliteSaver - -from langchain_anthropic +from langgraph.graph import END, MessageGraph +from langgraph.prebuilt.tool_node import ToolNode -# Define the chatbot state -class ChatbotState(TypedDict): - conversation_history: Annotated[ConversationHistory, operator.add] - pending_human_request: Optional[HumanRequest] - -# Create nodes for the chatbot and human -def chatbot(state: ChatbotState): - # TODO - -def human(state: ChatbotState): - # TODO - -# Create the graph -graph = StateGraph(ChatbotState) -graph.add_node("chatbot", chatbot) -graph.add_node("human", human) - -# Define routing logic between chatbot and human -def should_escalate(state): - if state['pending_human_request']: - return "human" +# Define the function that determines whether to continue or not +def should_continue(messages): + last_message = messages[-1] + # If there is no function call, then we finish + if not last_message.tool_calls: + return END else: - return "chatbot" + return "action" -graph.add_conditional_edges("chatbot", should_escalate, { - "human": "human", - "chatbot": "chatbot" -}) -graph.add_edge("human", "chatbot") +# Define a new graph +workflow = MessageGraph() -memory = SqliteSaver.from_conn_string(":memory:") -app = graph.compile(checkpointer=memory) -# Run the graph -result = app.invoke(new_user_message) +tools = [TavilySearchResults(max_results=1)] +model = ChatAnthropic(model="claude-3-haiku-20240307").bind_tools(tools) +workflow.add_node("agent", model) +workflow.add_node("action", ToolNode(tools)) + +workflow.set_entry_point("agent") + +# Conditional agent -> action OR agent -> END +workflow.add_conditional_edges( + "agent", + should_continue, +) + +# Always transition `action` -> `agent` +workflow.add_edge("action", "agent") + +memory = SqliteSaver.from_conn_string(":memory:") # Here we only save in-memory + +# Setting the interrupt means that any time an action is called, the machine will stop +app = workflow.compile(checkpointer=memory, interrupt_before=["action"]) ``` -The graph handles all the hard parts: +Now, run the graph: -- `conversation_history` in the state contains the assistant's "memory" -- Conditional edges enable dynamic routing between the chatbot and human based on the chatbot's confidence -- Persistence makes it easy to route to a human so they can respond and resume at any time +```python +# Run the graph +thread = {"configurable": {"thread_id": "4"}} +for event in app.stream("what is the weather in sf currently", thread): + for v in event.values(): + print(v) + +``` +We configured the graph to **wait** before executing the `action`. The `SqliteSaver` persists the state. Resume at any time. + +```python +for event in app.stream(None, thread): + for v in event.values(): + print(v) +``` + +The graph orchestrates everything: + +- The `MessageGraph` contains the agent's "Memory" +- Conditional edges enable dynamic routing between the chatbot, tools, and the user +- Persistence makes it easy to stop, resume, and even rewind for full control over your application With LangGraph, you can build complex, stateful agents without getting bogged down in manual state and interrupt management. Just define your nodes, edges, and state schema - and let the graph take care of the rest. -## Concepts - -- [Graphs](concepts.md#graphs) -- [State](concepts.md#state): The data structure passed between nodes, allowing you to persist context -- [Nodes](concepts.#nodes): The building blocks of your graph - LLMs, tools, or custom logic -- [Edges](concepts.md#edges): The connections that define the flow of data between your nodes -- [Conditional Edges](concepts.md#conditional_edges): Special edges that let you dynamically route between nodes based on state -- [Persistence](concepts.md#persistence): Save and resume your graph's state for long-running applications - -## How-To Guides - -Check out the [How-To Guides](how-tos/index.md) for instructions on handling common tasks with LangGraph. - -- Manage State -- Tool Integration -- Human-in-the-Loop -- Async Execution -- Streaming Responses -- Subgraphs & Branching -- Persistence, Visualization, Time Travel -- Benchmarking ## Tutorials -Consult the [Tutorials](tutorials/index.md) to learn more about implementing advanced +Consult the [Tutorials](tutorials/index.md) to learn more about building with LangGraph, including advanced use cases. -- **Agent Executors**: Chat and Langchain agents -- **Planning Agents**: Plan-and-Execute, ReWOO, LLMCompiler -- **Reflection & Critique**: Improving quality via reflection -- **Multi-Agent Systems**: Collaboration, supervision, teams -- **Research & QA**: Web research, retrieval-augmented QA -- **Applications**: Chatbots, code assist, web tasks -- **Evaluation & Analysis**: Simulation, self-discovery, swarms + +## How-To Guides + +Check out the [How-To Guides](how-tos/index.md) for instructions on handling common tasks with LangGraph ## Why LangGraph? -LangGraph extends the core strengths of LangChain Runnables (shared interface for streaming, async, and batch calls) to make it easy to: +LangGraph is framework agnostic (each node is a regular python function). It extends the core Runnable API (shared interface for streaming, async, and batch calls) to make it easy to: - Seamless state management across multiple turns of conversation or tool usage - The ability to flexibly route between nodes based on dynamic criteria - Smooth switching between LLMs and human intervention - Persistence for long-running, multi-session applications -If you're building a straightforward DAG,, LangChain expression language is a great fit. But for more complex, stateful applications with nonlinear flows, LangGraph is the perfect tool for the job. \ No newline at end of file +If you're building a straightforward DAG, Runnables are a great fit. But for more complex, stateful applications with nonlinear flows, LangGraph is the perfect tool for the job. \ No newline at end of file diff --git a/docs/docs/reference/checkpoints.md b/docs/docs/reference/checkpoints.md index e71634330..e93d4d8e5 100644 --- a/docs/docs/reference/checkpoints.md +++ b/docs/docs/reference/checkpoints.md @@ -1,11 +1,4 @@ # Checkpoints - ::: langgraph.checkpoint handler: python - options: - selection: - docstring_style: google - rendering: - heading_level: 3 - show_root_toc_entry: false \ No newline at end of file diff --git a/docs/docs/reference/graphs.md b/docs/docs/reference/graphs.md index b21f65b5d..70127f505 100644 --- a/docs/docs/reference/graphs.md +++ b/docs/docs/reference/graphs.md @@ -1,11 +1,12 @@ -# StateGraph - +# Graph Definitions ::: langgraph.graph handler: python - options: - selection: - docstring_style: google - rendering: - heading_level: 3 - show_root_toc_entry: false \ No newline at end of file + +## CompiledGraph + +::: langgraph.graph.graph.CompiledGraph + handler: python + members: + - get_graph + - invoke \ No newline at end of file diff --git a/docs/docs/reference/prebuilt.md b/docs/docs/reference/prebuilt.md index 7cb2ada1b..832921b02 100644 --- a/docs/docs/reference/prebuilt.md +++ b/docs/docs/reference/prebuilt.md @@ -1,11 +1,48 @@ -# Prebuilt +# Prebuilt +## ToolNode -::: langgraph.prebuilt +```python +from langgraph.prebuilt import ToolNode +``` + +::: langgraph.prebuilt.ToolNode handler: python - options: - selection: - docstring_style: google - rendering: - heading_level: 3 - show_root_toc_entry: false \ No newline at end of file + + +## ToolExecutor + +```python +from langgraph.prebuilt import ToolExecutor +``` + +::: langgraph.prebuilt.ToolExecutor + handler: python + + +## ToolInvocation + +```python +from langgraph.prebuilt import ToolInvocation +``` + +::: langgraph.prebuilt.ToolInvocation + handler: python + heading_level: 4 + + +## `chat_agent_executor.create_tool_calling_executor` + +```python +from langgraph.prebuilt.chat_agent_executor import create_tool_calling_executor +``` + +::: langgraph.prebuilt.chat_agent_executor + +## `create_agent_executor` + +```python +from langgraph.prebuilt import create_agent_executor +``` + +::: langgraph.prebuilt.create_agent_executor diff --git a/docs/docs/static/favicon.png b/docs/docs/static/favicon.png new file mode 100644 index 000000000..1dc08f512 Binary files /dev/null and b/docs/docs/static/favicon.png differ diff --git a/docs/docs/static/wordmark.png b/docs/docs/static/wordmark.png new file mode 100644 index 000000000..ba0be2763 Binary files /dev/null and b/docs/docs/static/wordmark.png differ diff --git a/docs/docs/tutorials/index.md b/docs/docs/tutorials/index.md index d00e01493..112a3ad6d 100644 --- a/docs/docs/tutorials/index.md +++ b/docs/docs/tutorials/index.md @@ -1,69 +1,69 @@ # Tutorials -Welcome to the LangGraph Tutorials! These notebooks provide end-to-end walkthroughs for building various types of language agents and applications using LangGraph. +Welcome to the LangGraph Tutorials! These notebooks introduce LangGraph through building various language agents and applications. -## Agent Executors +## AgentExecutor -- **Chat Agent (Function Calling)** - - [Base](chat_agent_executor_with_function_calling/base.ipynb): Implementing a chat agent executor with function calling - - [High-Level](chat_agent_executor_with_function_calling/high-level.ipynb): Using the high-level chat agent executor API - - [High-Level Tools](chat_agent_executor_with_function_calling/high-level-tools.ipynb): Integrating tools into the high-level chat agent executor - - **Modifications** - - [Human-in-the-Loop](chat_agent_executor_with_function_calling/human-in-the-loop.ipynb) - - [Force Tool First](chat_agent_executor_with_function_calling/force-calling-a-tool-first.ipynb) - - [Respond in Format](chat_agent_executor_with_function_calling/respond-in-format.ipynb) - - [Dynamic Direct Return](chat_agent_executor_with_function_calling/dynamically-returning-directly.ipynb) - - [Manage Agent Steps](chat_agent_executor_with_function_calling/managing-agent-steps.ipynb) +Learn to build a simple agent in LangGraph. -- **LangChain Agent** - - [Base](agent_executor/base.ipynb): Implementing an agent executor with Langchain agents - - [High-Level](agent_executor/high-level.ipynb): Using the high-level Langchain agent executor API - - **Modifications** - - [Human-in-the-Loop](agent_executor/human-in-the-loop.ipynb) - - [Force Tool First](agent_executor/force-calling-a-tool-first.ipynb) - - [Manage Agent Steps](agent_executor/managing-agent-steps.ipynb) +- [Base](agent_executor/base.ipynb): Learn to build a LangGraph agent "from scratch" +- [High-Level](agent_executor/high-level.ipynb): Learn to use the `create_agent_executor` -## Planning Agents +## Chat Agent Executor -- [Plan-and-Execute](plan-and-execute/plan-and-execute.ipynb): Implementing a basic planning and execution agent -- [Reasoning without Observation](rewoo/rewoo.ipynb): Reducing re-planning by saving observations as variables -- [LLMCompiler](llm-compiler/LLMCompiler.ipynb): Streaming and eagerly executing a DAG of tasks from a planner +Learn to build a simple chat agent executor, which is a basic graph with an agentic loop that also supports dialog with a user. -## Reflection & Critique +- [Base](chat_agent_executor_with_function_calling/base.ipynb): Build a chat agent executor with function calling +- [High-Level](chat_agent_executor_with_function_calling/high-level.ipynb): Using the high-level chat agent executor API +- [High-Level Tools](chat_agent_executor_with_function_calling/high-level-tools.ipynb): Integrating tools into the high-level chat agent executor -- [Basic Reflection](reflection/reflection.ipynb): Prompting the agent to reflect on and revise its outputs -- [Reflexion](reflexion/reflexion.ipynb): Critiquing missing and superfluous details to guide next steps -- [Language Agent Tree Search](lats/lats.ipynb): Using reflection and rewards to drive a tree search over agents +## Use cases -## Multi-Agent Systems +Learn from example implementations of graphs designed for specific scenarios and that implement common design patterns. + +#### Chatbots + +- [Customer Support](chatbots/customer-support.ipynb): Building a customer support chatbot +- [Info Gathering](chatbots/information-gather-prompting.ipynb): Building an information gathering chatbot +- [Code Assistant](code_assistant/langgraph_code_assistant.ipynb): Building a code analysis and generation assistant +- [Web Navigation](web-navigation/web_voyager.ipynb): Building an agent that can navigate and interact with websites + + +#### Multi-Agent Systems - [Collaboration](multi_agent/multi-agent-collaboration.ipynb): Enabling two agents to collaborate on a task - [Supervision](multi_agent/agent_supervisor.ipynb): Using an LLM to orchestrate and delegate to individual agents - [Hierarchical Teams](multi_agent/hierarchical_agent_teams.ipynb): Orchestrating nested teams of agents to solve problems -## Research & QA +#### RAG + +- [Adaptive RAG](rag/langgraph_adaptive_rag.ipynb) + - [Adaptive RAG using Cohere](rag/langgraph_adaptive_rag_cohere.ipynb) + - [Adaptive RAG using local models](rag/langgraph_adaptive_rag_local.ipynb) +- [Agentic RAG.ipynb](rag/langgraph_agentic_rag.ipynb) +- [Corrective RAG](rag/langgraph_crag.ipynb) + - [Corrective RAG with local models](rag/langgraph_crag_local.ipynb) +- [Self-RAG](rag/langgraph_self_rag.ipynb) + - [Self-RAG with local models](rag/langgraph_self_rag_local.ipynb) -- **Retrieval-Augmented Generation** - - [langgraph_adaptive_rag.ipynb](rag/langgraph_adaptive_rag.ipynb) - - [langgraph_adaptive_rag_cohere.ipynb](rag/langgraph_adaptive_rag_cohere.ipynb) - - [langgraph_adaptive_rag_local.ipynb](rag/langgraph_adaptive_rag_local.ipynb) - - [langgraph_agentic_rag.ipynb](rag/langgraph_agentic_rag.ipynb) - - [langgraph_crag.ipynb](rag/langgraph_crag.ipynb) - - [langgraph_crag_local.ipynb](rag/langgraph_crag_local.ipynb) - - [langgraph_self_rag.ipynb](rag/langgraph_self_rag.ipynb) - - [langgraph_self_rag_local.ipynb](rag/langgraph_self_rag_local.ipynb) - [Web Research (STORM)](storm/storm.ipynb): Generating Wikipedia-like articles via research and multi-perspective QA -## Applications -- **Chatbots** - - [Customer Support](chatbots/customer-support.ipynb): Building a customer support chatbot - - [Info Gathering](chatbots/information-gather-prompting.ipynb): Building an information gathering chatbot -- [Code Assistant](code_assistant/langgraph_code_assistant.ipynb): Building a code analysis and generation assistant -- [Web Navigation](web-navigation/web_voyager.ipynb): Building an agent that can navigate and interact with websites +#### Planning Agents -## Evaluation & Analysis +- [Plan-and-Execute](plan-and-execute/plan-and-execute.ipynb): Implementing a basic planning and execution agent +- [Reasoning without Observation](rewoo/rewoo.ipynb): Reducing re-planning by saving observations as variables +- [LLMCompiler](llm-compiler/LLMCompiler.ipynb): Streaming and eagerly executing a DAG of tasks from a planner -- **Chatbot Evaluation via Simulation** - - [Agent-based](chatbot-simulation-evaluation/agent-simulation-evaluation.ipynb): Evaluating chatbots via simulated user interactions - - [Dataset-based](chatbot-simulation-evaluation/langsmith-agent-simulation-evaluation.ipynb): Evaluating chatbots over a dialog dataset \ No newline at end of file +#### Reflection & Critique + +- [Basic Reflection](reflection/reflection.ipynb): Prompting the agent to reflect on and revise its outputs +- [Reflexion](reflexion/reflexion.ipynb): Critiquing missing and superfluous details to guide next steps +- [Language Agent Tree Search](lats/lats.ipynb): Using reflection and rewards to drive a tree search over agents +- [Self-Discovering Agent](self-discover/self-discover.ipynb): Analyzing an agent that learns about its own capabilities + + +#### Evaluation + +- [Agent-based](chatbot-simulation-evaluation/agent-simulation-evaluation.ipynb): Evaluating chatbots via simulated user interactions +- [Dataset-based](chatbot-simulation-evaluation/langsmith-agent-simulation-evaluation.ipynb): Evaluating chatbots in LangSmith over a dialog dataset \ No newline at end of file diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 8621901a1..b06bbceeb 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -4,8 +4,8 @@ site_url: https://langchain-ai.github.io/langgraph/ theme: name: material custom_dir: overrides - logo: static/img/brand/wordmark.png - favicon: static/img/brand/favicon.png + logo: static/wordmark.png + favicon: static/favicon.png features: - announce.dismiss - content.action.edit @@ -54,10 +54,25 @@ plugins: - mkdocstrings: handlers: python: + import: + - https://docs.python.org/3/objects.inv + - https://api.python.langchain.com/en/latest/objects.inv options: members_order: source allow_inspection: true + heading_level: 3 show_bases: true + summary: true + inherited_members: true + # merge_init_into_class: true + selection: + docstring_style: google + docstring_section_style: list + show_root_toc_entry: false + # show_signature_annotations: true + # show_symbol_type_heading: true + show_symbol_type_toc: true + signature_crossrefs: true - mkdocs-jupyter: ignore_h1_titles: true execute: false @@ -69,83 +84,82 @@ plugins: nav: - Home: - 'index.md' - - Quick Start: quick_start.ipynb - - Concepts: - - 'concepts.md' - - "How-to Guides": - - Basics: - - State Management: how-tos/state-model.ipynb - - Tool Integration: how-tos/sql_example.ipynb - - Human-in-the-Loop: how-tos/human-in-the-loop.ipynb - - Performance: - - Async Execution: how-tos/async.ipynb - - Streaming Responses: how-tos/streaming-tokens.ipynb - - Graph Structure: - - Subgraphs: how-tos/subgraph.ipynb - - Branching: how-tos/branching.ipynb - - Development: - - Persistence: how-tos/persistence.ipynb - - Visualization: how-tos/visualization.ipynb - - Time Travel: how-tos/time-travel.ipynb - - Benchmarking: how-tos/swe-bench.ipynb + - Quick Start: how-tos/docs/quickstart.ipynb - Tutorials: - - Agent Executors: - - Chat Agent (Function Calling): - - Base: tutorials/chat_agent_executor_with_function_calling/base.ipynb - - High-Level: tutorials/chat_agent_executor_with_function_calling/high-level.ipynb - - High-Level Tools: tutorials/chat_agent_executor_with_function_calling/high-level-tools.ipynb - - Modifications: - - Human-in-the-Loop: tutorials/chat_agent_executor_with_function_calling/human-in-the-loop.ipynb - - Force Tool First: tutorials/chat_agent_executor_with_function_calling/force-calling-a-tool-first.ipynb - - Respond in Format: tutorials/chat_agent_executor_with_function_calling/respond-in-format.ipynb - - Dynamic Direct Return: tutorials/chat_agent_executor_with_function_calling/dynamically-returning-directly.ipynb - - Manage Agent Steps: tutorials/chat_agent_executor_with_function_calling/managing-agent-steps.ipynb - - Langchain Agent: - - Base: tutorials/agent_executor/base.ipynb - - High-Level: tutorials/agent_executor/high-level.ipynb - - Modifications: - - Human-in-the-Loop: tutorials/agent_executor/human-in-the-loop.ipynb - - Force Tool First: tutorials/agent_executor/force-calling-a-tool-first.ipynb - - Manage Agent Steps: tutorials/agent_executor/managing-agent-steps.ipynb - - Planning Agents: - - Plan-and-Execute: tutorials/plan-and-execute/plan-and-execute.ipynb - - Reasoning w/o Observation: tutorials/rewoo/rewoo.ipynb - - LLMCompiler: tutorials/llm-compiler/LLMCompiler.ipynb - - Reflection & Critique: - - Basic Reflection: tutorials/reflection/reflection.ipynb - - Reflexion: tutorials/reflexion/reflexion.ipynb - - Language Agent Tree Search: tutorials/lats/lats.ipynb - - Multi-Agent Systems: - - Collaboration: tutorials/multi_agent/multi-agent-collaboration.ipynb - - Supervision: tutorials/multi_agent/agent_supervisor.ipynb - - Hierarchical Teams: tutorials/multi_agent/hierarchical_agent_teams.ipynb - - Research & QA: - - Web Research (STORM): tutorials/storm/storm.ipynb - - Retrieval-Augmented Generation: + - 'tutorials/index.md' + - Agent Executor: + - "Base": tutorials/agent_executor/base.ipynb + - "High-Level": tutorials/agent_executor/high-level.ipynb + - Chat Agent Executor: + - "Base": tutorials/chat_agent_executor_with_function_calling/base.ipynb + - "High-Level": tutorials/chat_agent_executor_with_function_calling/high-level.ipynb + - "Tool Node": tutorials/chat_agent_executor_with_function_calling/prebuilt-tool-node.ipynb + - "High-Level Tools": tutorials/chat_agent_executor_with_function_calling/high-level-tools.ipynb + - Use cases: + - Chatbots: + - Customer Support: tutorials/chatbots/customer-support.ipynb + - Info Gathering: tutorials/chatbots/information-gather-prompting.ipynb + - Code Assistant: tutorials/code_assistant/langgraph_code_assistant.ipynb + - Web Navigation: tutorials/web-navigation/web_voyager.ipynb + - Multi-Agent Systems: + - Collaboration: tutorials/multi_agent/multi-agent-collaboration.ipynb + - Supervision: tutorials/multi_agent/agent_supervisor.ipynb + - Hierarchical Teams: tutorials/multi_agent/hierarchical_agent_teams.ipynb + - RAG: - tutorials/rag/langgraph_adaptive_rag.ipynb - tutorials/rag/langgraph_adaptive_rag_cohere.ipynb - tutorials/rag/langgraph_adaptive_rag_local.ipynb - - tutorials/rag/langgraph_agentic_rag.ipynb + - tutorials/rag/langgraph_agentic_rag.ipynb - tutorials/rag/langgraph_crag.ipynb - tutorials/rag/langgraph_crag_local.ipynb - - tutorials/rag/langgraph_self_rag.ipynb + - tutorials/rag/langgraph_self_rag.ipynb - tutorials/rag/langgraph_self_rag_local.ipynb - - Applications: - - Chatbots: - - Customer Support: tutorials/chatbots/customer-support.ipynb - - Info Gathering: tutorials/chatbots/information-gather-prompting.ipynb - - Code Assistant: tutorials/code_assistant/langgraph_code_assistant.ipynb - - Web Navigation: tutorials/web-navigation/web_voyager.ipynb - - Evaluation & Analysis: - - Chatbot Eval via Sim: - - Agent-based: tutorials/chatbot-simulation-evaluation/agent-simulation-evaluation.ipynb - - Dataset-based: tutorials/chatbot-simulation-evaluation/langsmith-agent-simulation-evaluation.ipynb - - Self-Discovering Agent: tutorials/self-discover/self-discover.ipynb - - Swarm: tutorials/gptswarm/swarm.ipynb + - Web Research (STORM): tutorials/storm/storm.ipynb + - Planning Agents: + - Plan-and-Execute: tutorials/plan-and-execute/plan-and-execute.ipynb + - Reasoning w/o Observation: tutorials/rewoo/rewoo.ipynb + - LLMCompiler: tutorials/llm-compiler/LLMCompiler.ipynb + - Reflection & Critique: + - Basic Reflection: tutorials/reflection/reflection.ipynb + - Reflexion: tutorials/reflexion/reflexion.ipynb + - Language Agent Tree Search: tutorials/lats/lats.ipynb + - Self-Discovering Agent: tutorials/self-discover/self-discover.ipynb + - Evaluation & Analysis: + - Chatbot Eval via Sim: + - Agent-based: tutorials/chatbot-simulation-evaluation/agent-simulation-evaluation.ipynb + - Dataset-based: tutorials/chatbot-simulation-evaluation/langsmith-agent-simulation-evaluation.ipynb + + - "How-to Guides": + - 'how-tos/index.md' + - Core: + - "Quick Start": how-tos/docs/quickstart.ipynb + - "State Management": how-tos/state-model.ipynb + - "Async Execution": how-tos/async.ipynb + - "Streaming Responses": how-tos/streaming-tokens.ipynb + - "Human-in-the-Loop": how-tos/human-in-the-loop.ipynb + - "Persistence": how-tos/persistence.ipynb + - "Time Travel": how-tos/time-travel.ipynb + - "Visualization": how-tos/visualization.ipynb + - "Pydantic State": how-tos/state-model.ipynb + - "Subgraphs": how-tos/subgraph.ipynb + - "Branching": how-tos/branching.ipynb + - Chat Agent (Function Calling): + - Human-in-the-Loop: how-tos/chat_agent_executor_with_function_calling/human-in-the-loop.ipynb + - Force Tool First: how-tos/chat_agent_executor_with_function_calling/force-calling-a-tool-first.ipynb + - Respond in Format: how-tos/chat_agent_executor_with_function_calling/respond-in-format.ipynb + - Dynamic Direct Return: how-tos/chat_agent_executor_with_function_calling/dynamically-returning-directly.ipynb + - Manage Agent Steps: how-tos/chat_agent_executor_with_function_calling/managing-agent-steps.ipynb + - AgentExecutor: + - Human-in-the-Loop: how-tos/agent_executor/human-in-the-loop.ipynb + - Force Tool First: how-tos/agent_executor/force-calling-a-tool-first.ipynb + - Manage Agent Steps: how-tos/agent_executor/managing-agent-steps.ipynb + - Persistance: + - "Persistance in Postgres": how-tos/persistence_postgres.ipynb + - Reference: - Graphs: reference/graphs.md - Checkpointing: reference/checkpoints.md - - Prebuilt Components: reference/prebuilt_components.md + - Prebuilt Components: reference/prebuilt.md markdown_extensions: diff --git a/examples/code_assistant/langgraph_code_assistant.ipynb b/examples/code_assistant/langgraph_code_assistant.ipynb index e7b86b832..19db6e88d 100644 --- a/examples/code_assistant/langgraph_code_assistant.ipynb +++ b/examples/code_assistant/langgraph_code_assistant.ipynb @@ -684,7 +684,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.8" + "version": "3.11.2" } }, "nbformat": 4, diff --git a/examples/rag/langgraph_adaptive_rag.ipynb b/examples/rag/langgraph_adaptive_rag.ipynb index 12d558691..55cb61f4c 100644 --- a/examples/rag/langgraph_adaptive_rag.ipynb +++ b/examples/rag/langgraph_adaptive_rag.ipynb @@ -42,190 +42,12 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "53d1a740-9fea-4a6e-8f95-fb9dbf1c80a1", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Requirement already satisfied: langchain_community in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (0.0.27)\n", - "Collecting langchain_community\n", - " Downloading langchain_community-0.0.31-py3-none-any.whl.metadata (8.4 kB)\n", - "Requirement already satisfied: tiktoken in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (0.5.2)\n", - "Collecting tiktoken\n", - " Downloading tiktoken-0.6.0-cp311-cp311-macosx_11_0_arm64.whl.metadata (6.6 kB)\n", - "Requirement already satisfied: langchain-openai in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (0.0.2.post1)\n", - "Collecting langchain-openai\n", - " Downloading langchain_openai-0.1.1-py3-none-any.whl.metadata (2.5 kB)\n", - "Requirement already satisfied: langchain-cohere in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (0.1.0)\n", - "Requirement already satisfied: langchainhub in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (0.1.15)\n", - "Requirement already satisfied: chromadb in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (0.4.24)\n", - "Requirement already satisfied: langchain in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (0.1.11)\n", - "Collecting langchain\n", - " Downloading langchain-0.1.14-py3-none-any.whl.metadata (13 kB)\n", - "Requirement already satisfied: langgraph in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (0.0.30)\n", - "Collecting langgraph\n", - " Downloading langgraph-0.0.31-py3-none-any.whl.metadata (44 kB)\n", - "\u001b[2K \u001b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m44.8/44.8 kB\u001b[0m \u001b[31m782.7 kB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m31m1.0 MB/s\u001b[0m eta \u001b[36m0:00:01\u001b[0m\n", - "\u001b[?25hRequirement already satisfied: tavily-python in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (0.3.1)\n", - "Collecting tavily-python\n", - " Downloading tavily_python-0.3.3-py3-none-any.whl.metadata (4.4 kB)\n", - "Requirement already satisfied: PyYAML>=5.3 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from langchain_community) (6.0.1)\n", - "Requirement already satisfied: SQLAlchemy<3,>=1.4 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from langchain_community) (2.0.28)\n", - "Requirement already satisfied: aiohttp<4.0.0,>=3.8.3 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from langchain_community) (3.9.3)\n", - "Requirement already satisfied: dataclasses-json<0.7,>=0.5.7 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from langchain_community) (0.6.4)\n", - "Requirement already satisfied: langchain-core<0.2.0,>=0.1.37 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from langchain_community) (0.1.38)\n", - "Requirement already satisfied: langsmith<0.2.0,>=0.1.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from langchain_community) (0.1.23)\n", - "Requirement already satisfied: numpy<2,>=1 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from langchain_community) (1.26.4)\n", - "Requirement already satisfied: requests<3,>=2 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from langchain_community) (2.31.0)\n", - "Requirement already satisfied: tenacity<9.0.0,>=8.1.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from langchain_community) (8.2.3)\n", - "Requirement already satisfied: regex>=2022.1.18 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from tiktoken) (2023.12.25)\n", - "Requirement already satisfied: openai<2.0.0,>=1.10.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from langchain-openai) (1.13.3)\n", - "Requirement already satisfied: cohere<6.0.0,>=5.1.4 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from langchain-cohere) (5.1.7)\n", - "Requirement already satisfied: types-requests<3.0.0.0,>=2.31.0.2 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from langchainhub) (2.31.0.20240311)\n", - "Requirement already satisfied: build>=1.0.3 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from chromadb) (1.2.1)\n", - "Requirement already satisfied: pydantic>=1.9 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from chromadb) (2.6.4)\n", - "Requirement already satisfied: chroma-hnswlib==0.7.3 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from chromadb) (0.7.3)\n", - "Requirement already satisfied: fastapi>=0.95.2 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from chromadb) (0.109.0)\n", - "Requirement already satisfied: uvicorn>=0.18.3 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from uvicorn[standard]>=0.18.3->chromadb) (0.25.0)\n", - "Requirement already satisfied: posthog>=2.4.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from chromadb) (3.5.0)\n", - "Requirement already satisfied: typing-extensions>=4.5.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from chromadb) (4.10.0)\n", - "Requirement already satisfied: pulsar-client>=3.1.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from chromadb) (3.4.0)\n", - "Requirement already satisfied: onnxruntime>=1.14.1 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from chromadb) (1.17.1)\n", - "Requirement already satisfied: opentelemetry-api>=1.2.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from chromadb) (1.24.0)\n", - "Requirement already satisfied: opentelemetry-exporter-otlp-proto-grpc>=1.2.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from chromadb) (1.24.0)\n", - "Requirement already satisfied: opentelemetry-instrumentation-fastapi>=0.41b0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from chromadb) (0.45b0)\n", - "Requirement already satisfied: opentelemetry-sdk>=1.2.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from chromadb) (1.24.0)\n", - "Requirement already satisfied: tokenizers>=0.13.2 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from chromadb) (0.15.2)\n", - "Requirement already satisfied: pypika>=0.48.9 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from chromadb) (0.48.9)\n", - "Requirement already satisfied: tqdm>=4.65.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from chromadb) (4.66.2)\n", - "Requirement already satisfied: overrides>=7.3.1 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from chromadb) (7.7.0)\n", - "Requirement already satisfied: importlib-resources in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from chromadb) (6.4.0)\n", - "Requirement already satisfied: grpcio>=1.58.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from chromadb) (1.62.1)\n", - "Requirement already satisfied: bcrypt>=4.0.1 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from chromadb) (4.1.2)\n", - "Requirement already satisfied: typer>=0.9.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from chromadb) (0.12.0)\n", - "Requirement already satisfied: kubernetes>=28.1.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from chromadb) (29.0.0)\n", - "Requirement already satisfied: mmh3>=4.0.1 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from chromadb) (4.1.0)\n", - "Requirement already satisfied: orjson>=3.9.12 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from chromadb) (3.9.15)\n", - "Requirement already satisfied: jsonpatch<2.0,>=1.33 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from langchain) (1.33)\n", - "Requirement already satisfied: langchain-text-splitters<0.1,>=0.0.1 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from langchain) (0.0.1)\n", - "Requirement already satisfied: aiosignal>=1.1.2 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from aiohttp<4.0.0,>=3.8.3->langchain_community) (1.3.1)\n", - "Requirement already satisfied: attrs>=17.3.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from aiohttp<4.0.0,>=3.8.3->langchain_community) (23.2.0)\n", - "Requirement already satisfied: frozenlist>=1.1.1 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from aiohttp<4.0.0,>=3.8.3->langchain_community) (1.4.1)\n", - "Requirement already satisfied: multidict<7.0,>=4.5 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from aiohttp<4.0.0,>=3.8.3->langchain_community) (6.0.5)\n", - "Requirement already satisfied: yarl<2.0,>=1.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from aiohttp<4.0.0,>=3.8.3->langchain_community) (1.9.4)\n", - "Requirement already satisfied: packaging>=19.1 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from build>=1.0.3->chromadb) (23.2)\n", - "Requirement already satisfied: pyproject_hooks in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from build>=1.0.3->chromadb) (1.0.0)\n", - "Requirement already satisfied: fastavro<2.0.0,>=1.9.4 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from cohere<6.0.0,>=5.1.4->langchain-cohere) (1.9.4)\n", - "Requirement already satisfied: httpx>=0.21.2 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from cohere<6.0.0,>=5.1.4->langchain-cohere) (0.26.0)\n", - "Requirement already satisfied: marshmallow<4.0.0,>=3.18.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from dataclasses-json<0.7,>=0.5.7->langchain_community) (3.21.1)\n", - "Requirement already satisfied: typing-inspect<1,>=0.4.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from dataclasses-json<0.7,>=0.5.7->langchain_community) (0.9.0)\n", - "Requirement already satisfied: starlette<0.36.0,>=0.35.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from fastapi>=0.95.2->chromadb) (0.35.1)\n", - "Requirement already satisfied: jsonpointer>=1.9 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from jsonpatch<2.0,>=1.33->langchain) (2.4)\n", - "Requirement already satisfied: certifi>=14.05.14 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from kubernetes>=28.1.0->chromadb) (2024.2.2)\n", - "Requirement already satisfied: six>=1.9.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from kubernetes>=28.1.0->chromadb) (1.16.0)\n", - "Requirement already satisfied: python-dateutil>=2.5.3 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from kubernetes>=28.1.0->chromadb) (2.9.0.post0)\n", - "Requirement already satisfied: google-auth>=1.0.1 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from kubernetes>=28.1.0->chromadb) (2.29.0)\n", - "Requirement already satisfied: websocket-client!=0.40.0,!=0.41.*,!=0.42.*,>=0.32.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from kubernetes>=28.1.0->chromadb) (1.7.0)\n", - "Requirement already satisfied: requests-oauthlib in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from kubernetes>=28.1.0->chromadb) (2.0.0)\n", - "Requirement already satisfied: oauthlib>=3.2.2 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from kubernetes>=28.1.0->chromadb) (3.2.2)\n", - "Requirement already satisfied: urllib3>=1.24.2 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from kubernetes>=28.1.0->chromadb) (2.2.1)\n", - "Requirement already satisfied: coloredlogs in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from onnxruntime>=1.14.1->chromadb) (15.0.1)\n", - "Requirement already satisfied: flatbuffers in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from onnxruntime>=1.14.1->chromadb) (24.3.25)\n", - "Requirement already satisfied: protobuf in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from onnxruntime>=1.14.1->chromadb) (4.25.3)\n", - "Requirement already satisfied: sympy in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from onnxruntime>=1.14.1->chromadb) (1.12)\n", - "Requirement already satisfied: anyio<5,>=3.5.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from openai<2.0.0,>=1.10.0->langchain-openai) (4.3.0)\n", - "Requirement already satisfied: distro<2,>=1.7.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from openai<2.0.0,>=1.10.0->langchain-openai) (1.9.0)\n", - "Requirement already satisfied: sniffio in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from openai<2.0.0,>=1.10.0->langchain-openai) (1.3.1)\n", - "Requirement already satisfied: deprecated>=1.2.6 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from opentelemetry-api>=1.2.0->chromadb) (1.2.14)\n", - "Requirement already satisfied: importlib-metadata<=7.0,>=6.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from opentelemetry-api>=1.2.0->chromadb) (7.0.0)\n", - "Requirement already satisfied: googleapis-common-protos~=1.52 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from opentelemetry-exporter-otlp-proto-grpc>=1.2.0->chromadb) (1.63.0)\n", - "Requirement already satisfied: opentelemetry-exporter-otlp-proto-common==1.24.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from opentelemetry-exporter-otlp-proto-grpc>=1.2.0->chromadb) (1.24.0)\n", - "Requirement already satisfied: opentelemetry-proto==1.24.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from opentelemetry-exporter-otlp-proto-grpc>=1.2.0->chromadb) (1.24.0)\n", - "Requirement already satisfied: opentelemetry-instrumentation-asgi==0.45b0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from opentelemetry-instrumentation-fastapi>=0.41b0->chromadb) (0.45b0)\n", - "Requirement already satisfied: opentelemetry-instrumentation==0.45b0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from opentelemetry-instrumentation-fastapi>=0.41b0->chromadb) (0.45b0)\n", - "Requirement already satisfied: opentelemetry-semantic-conventions==0.45b0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from opentelemetry-instrumentation-fastapi>=0.41b0->chromadb) (0.45b0)\n", - "Requirement already satisfied: opentelemetry-util-http==0.45b0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from opentelemetry-instrumentation-fastapi>=0.41b0->chromadb) (0.45b0)\n", - "Requirement already satisfied: setuptools>=16.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from opentelemetry-instrumentation==0.45b0->opentelemetry-instrumentation-fastapi>=0.41b0->chromadb) (69.0.2)\n", - "Requirement already satisfied: wrapt<2.0.0,>=1.0.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from opentelemetry-instrumentation==0.45b0->opentelemetry-instrumentation-fastapi>=0.41b0->chromadb) (1.16.0)\n", - "Requirement already satisfied: asgiref~=3.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from opentelemetry-instrumentation-asgi==0.45b0->opentelemetry-instrumentation-fastapi>=0.41b0->chromadb) (3.8.1)\n", - "Requirement already satisfied: monotonic>=1.5 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from posthog>=2.4.0->chromadb) (1.6)\n", - "Requirement already satisfied: backoff>=1.10.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from posthog>=2.4.0->chromadb) (2.2.1)\n", - "Requirement already satisfied: annotated-types>=0.4.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from pydantic>=1.9->chromadb) (0.6.0)\n", - "Requirement already satisfied: pydantic-core==2.16.3 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from pydantic>=1.9->chromadb) (2.16.3)\n", - "Requirement already satisfied: charset-normalizer<4,>=2 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from requests<3,>=2->langchain_community) (3.3.2)\n", - "Requirement already satisfied: idna<4,>=2.5 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from requests<3,>=2->langchain_community) (3.6)\n", - "Requirement already satisfied: huggingface_hub<1.0,>=0.16.4 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from tokenizers>=0.13.2->chromadb) (0.22.1)\n", - "Requirement already satisfied: typer-slim==0.12.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from typer-slim[standard]==0.12.0->typer>=0.9.0->chromadb) (0.12.0)\n", - "Requirement already satisfied: typer-cli==0.12.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from typer>=0.9.0->chromadb) (0.12.0)\n", - "Requirement already satisfied: click>=8.0.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from typer-slim==0.12.0->typer-slim[standard]==0.12.0->typer>=0.9.0->chromadb) (8.1.7)\n", - "Requirement already satisfied: shellingham>=1.3.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from typer-slim[standard]==0.12.0->typer>=0.9.0->chromadb) (1.5.4)\n", - "Requirement already satisfied: rich>=10.11.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from typer-slim[standard]==0.12.0->typer>=0.9.0->chromadb) (13.7.1)\n", - "Requirement already satisfied: h11>=0.8 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from uvicorn>=0.18.3->uvicorn[standard]>=0.18.3->chromadb) (0.14.0)\n", - "Requirement already satisfied: httptools>=0.5.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from uvicorn[standard]>=0.18.3->chromadb) (0.6.1)\n", - "Requirement already satisfied: python-dotenv>=0.13 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from uvicorn[standard]>=0.18.3->chromadb) (1.0.1)\n", - "Requirement already satisfied: uvloop!=0.15.0,!=0.15.1,>=0.14.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from uvicorn[standard]>=0.18.3->chromadb) (0.19.0)\n", - "Requirement already satisfied: watchfiles>=0.13 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from uvicorn[standard]>=0.18.3->chromadb) (0.21.0)\n", - "Requirement already satisfied: websockets>=10.4 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from uvicorn[standard]>=0.18.3->chromadb) (12.0)\n", - "Requirement already satisfied: cachetools<6.0,>=2.0.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from google-auth>=1.0.1->kubernetes>=28.1.0->chromadb) (5.3.3)\n", - "Requirement already satisfied: pyasn1-modules>=0.2.1 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from google-auth>=1.0.1->kubernetes>=28.1.0->chromadb) (0.4.0)\n", - "Requirement already satisfied: rsa<5,>=3.1.4 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from google-auth>=1.0.1->kubernetes>=28.1.0->chromadb) (4.9)\n", - "Requirement already satisfied: httpcore==1.* in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from httpx>=0.21.2->cohere<6.0.0,>=5.1.4->langchain-cohere) (1.0.4)\n", - "Requirement already satisfied: filelock in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from huggingface_hub<1.0,>=0.16.4->tokenizers>=0.13.2->chromadb) (3.13.3)\n", - "Requirement already satisfied: fsspec>=2023.5.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from huggingface_hub<1.0,>=0.16.4->tokenizers>=0.13.2->chromadb) (2024.3.1)\n", - "Requirement already satisfied: zipp>=0.5 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from importlib-metadata<=7.0,>=6.0->opentelemetry-api>=1.2.0->chromadb) (3.18.1)\n", - "Requirement already satisfied: mypy-extensions>=0.3.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from typing-inspect<1,>=0.4.0->dataclasses-json<0.7,>=0.5.7->langchain_community) (1.0.0)\n", - "Requirement already satisfied: humanfriendly>=9.1 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from coloredlogs->onnxruntime>=1.14.1->chromadb) (10.0)\n", - "Requirement already satisfied: mpmath>=0.19 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from sympy->onnxruntime>=1.14.1->chromadb) (1.3.0)\n", - "Requirement already satisfied: pyasn1<0.7.0,>=0.4.6 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from pyasn1-modules>=0.2.1->google-auth>=1.0.1->kubernetes>=28.1.0->chromadb) (0.6.0)\n", - "Requirement already satisfied: markdown-it-py>=2.2.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from rich>=10.11.0->typer-slim[standard]==0.12.0->typer>=0.9.0->chromadb) (3.0.0)\n", - "Requirement already satisfied: pygments<3.0.0,>=2.13.0 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from rich>=10.11.0->typer-slim[standard]==0.12.0->typer>=0.9.0->chromadb) (2.17.2)\n", - "Requirement already satisfied: mdurl~=0.1 in /Users/nuno/dev/langgraph/.venv/lib/python3.11/site-packages (from markdown-it-py>=2.2.0->rich>=10.11.0->typer-slim[standard]==0.12.0->typer>=0.9.0->chromadb) (0.1.2)\n", - "Downloading langchain_community-0.0.31-py3-none-any.whl (1.9 MB)\n", - "\u001b[2K \u001b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.9/1.9 MB\u001b[0m \u001b[31m9.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m[31m10.3 MB/s\u001b[0m eta \u001b[36m0:00:01\u001b[0m\n", - "\u001b[?25hDownloading tiktoken-0.6.0-cp311-cp311-macosx_11_0_arm64.whl (949 kB)\n", - "\u001b[2K \u001b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m949.8/949.8 kB\u001b[0m \u001b[31m15.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m31m20.3 MB/s\u001b[0m eta \u001b[36m0:00:01\u001b[0m\n", - "\u001b[?25hDownloading langchain_openai-0.1.1-py3-none-any.whl (32 kB)\n", - "Downloading langchain-0.1.14-py3-none-any.whl (812 kB)\n", - "\u001b[2K \u001b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m812.8/812.8 kB\u001b[0m \u001b[31m14.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m MB/s\u001b[0m eta \u001b[36m0:00:01\u001b[0m\n", - "\u001b[?25hDownloading langgraph-0.0.31-py3-none-any.whl (55 kB)\n", - "\u001b[2K \u001b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m55.5/55.5 kB\u001b[0m \u001b[31m4.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hDownloading tavily_python-0.3.3-py3-none-any.whl (5.4 kB)\n", - "Installing collected packages: tiktoken, tavily-python, langgraph, langchain-openai, langchain_community, langchain\n", - " Attempting uninstall: tiktoken\n", - " Found existing installation: tiktoken 0.5.2\n", - " Uninstalling tiktoken-0.5.2:\n", - " Successfully uninstalled tiktoken-0.5.2\n", - " Attempting uninstall: tavily-python\n", - " Found existing installation: tavily-python 0.3.1\n", - " Uninstalling tavily-python-0.3.1:\n", - " Successfully uninstalled tavily-python-0.3.1\n", - " Attempting uninstall: langgraph\n", - " Found existing installation: langgraph 0.0.30\n", - " Uninstalling langgraph-0.0.30:\n", - " Successfully uninstalled langgraph-0.0.30\n", - " Attempting uninstall: langchain-openai\n", - " Found existing installation: langchain-openai 0.0.2.post1\n", - " Uninstalling langchain-openai-0.0.2.post1:\n", - " Successfully uninstalled langchain-openai-0.0.2.post1\n", - " Attempting uninstall: langchain_community\n", - " Found existing installation: langchain-community 0.0.27\n", - " Uninstalling langchain-community-0.0.27:\n", - " Successfully uninstalled langchain-community-0.0.27\n", - " Attempting uninstall: langchain\n", - " Found existing installation: langchain 0.1.11\n", - " Uninstalling langchain-0.1.11:\n", - " Successfully uninstalled langchain-0.1.11\n", - "Successfully installed langchain-0.1.14 langchain-openai-0.1.1 langchain_community-0.0.31 langgraph-0.0.31 tavily-python-0.3.3 tiktoken-0.6.0\n", - "\n", - "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m23.3.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.0\u001b[0m\n", - "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n" - ] - } - ], + "outputs": [], "source": [ + "%%capture --no-stderr\n", "! pip install -U langchain_community tiktoken langchain-openai langchain-cohere langchainhub chromadb langchain langgraph tavily-python" ] }, diff --git a/langgraph/checkpoint/base.py b/langgraph/checkpoint/base.py index 6e3b2fc46..a48cd2a8b 100644 --- a/langgraph/checkpoint/base.py +++ b/langgraph/checkpoint/base.py @@ -69,8 +69,12 @@ def copy_checkpoint(checkpoint: Checkpoint) -> Checkpoint: class CheckpointAt(StrEnum): + """When to take a checkpoint.""" + END_OF_STEP = "end_of_step" + """Take a checkpoint at the end of each step.""" END_OF_RUN = "end_of_run" + """Take a checkpoint at the end of the run.""" class CheckpointTuple(NamedTuple): diff --git a/langgraph/graph/graph.py b/langgraph/graph/graph.py index 5830e3a9c..4ada73c1c 100644 --- a/langgraph/graph/graph.py +++ b/langgraph/graph/graph.py @@ -153,6 +153,24 @@ class Graph: ], conditional_edge_mapping: Optional[dict[str, str]] = None, ) -> None: + """Add a conditional edge from the starting node to any number of destination nodes. + + + Args: + start_key (str): The key of the starting node. + condition (Union[Callable, Runnable]): The condition that determines the destination of the edge. + conditional_edge_mapping (Optional[dict[str, str]]): A dictionary that maps the response of the condition to a name of + the destination node(s). If the condition returns a list, the response will be matched against the keys of the + dictionary. If the condition returns a string, the response will be matched against the values of the dictionary. + If the condition returns a string and the dictionary contains a key with the value of `END` ("__end__"`), + the graph will finish. + + Raises: + ValueError: If the starting node is not found in the graph or if the conditional edge mapping contains missing nodes. + + Returns: + None + """ # noqa: E501 if self.compiled: logger.warning( "Adding an edge to a graph that has already been compiled. This will " @@ -182,6 +200,14 @@ class Graph: self.branches[start_key][name] = Branch(condition, conditional_edge_mapping) def set_entry_point(self, key: str) -> None: + """Specifies the first node to be called in the graph. + + Parameters: + key (str): The key of the node to set as the entry point. + + Returns: + None + """ return self.add_edge(START, key) def set_conditional_entry_point( @@ -191,9 +217,28 @@ class Graph: ], conditional_edge_mapping: Optional[Dict[str, str]] = None, ) -> None: + """Sets a conditional entry point in the graph. + + Args: + condition: A callable object that takes any number of arguments and returns a string or an awaitable string. + conditional_edge_mapping: A dictionary that maps condition names to edge names. + + Returns: + None + """ return self.add_conditional_edges(START, condition, conditional_edge_mapping) def set_finish_point(self, key: str) -> None: + """Marks a node as a finish point of the graph. + + If the graph reaches this node, it will cease execution. + + Parameters: + key (str): The key of the node to set as the finish point. + + Returns: + None + """ return self.add_edge(key, END) def validate(self, interrupt: Optional[Sequence[str]] = None) -> None: diff --git a/langgraph/graph/state.py b/langgraph/graph/state.py index 33114a795..bc42d0370 100644 --- a/langgraph/graph/state.py +++ b/langgraph/graph/state.py @@ -45,11 +45,37 @@ class StateGraph(Graph): } def add_node(self, key: str, action: RunnableLike) -> None: + """Adds a new node to the state graph. + + Args: + key (str): The key of the node. + action (RunnableLike): The action associated with the node. + + Raises: + ValueError: If the key is already being used as a state key. + + Returns: + None + """ if key in self.channels: raise ValueError(f"'{key}' is already being used as a state key") return super().add_node(key, action) def add_edge(self, start_key: Union[str, list[str]], end_key: str) -> None: + """Adds a directed edge from the start node to the end node. + + If the graph transitions to the start_key node, it will always transition to the end_key node next. + + Args: + start_key (Union[str, list[str]]): The key(s) of the start node(s) of the edge. + end_key (str): The key of the end node of the edge. + + Raises: + ValueError: If the start key is 'END' or if the start key or end key is not present in the graph. + + Returns: + None + """ if isinstance(start_key, str): return super().add_edge(start_key, end_key) @@ -77,6 +103,17 @@ class StateGraph(Graph): interrupt_after: Optional[Sequence[str]] = None, debug: bool = False, ) -> CompiledGraph: + """Compiles the state graph into a `CompiledGraph` object. + + Args: + checkpointer (Optional[BaseCheckpointSaver]): An optional checkpoint saver object. + interrupt_before (Optional[Sequence[str]]): An optional list of node names to interrupt before. + interrupt_after (Optional[Sequence[str]]): An optional list of node names to interrupt after. + debug (bool): A flag indicating whether to enable debug mode. + + Returns: + CompiledGraph: The compiled state graph. + """ # assign default values interrupt_before = interrupt_before or [] interrupt_after = interrupt_after or [] @@ -135,10 +172,12 @@ class CompiledStateGraph(CompiledGraph): state_keys = list(self.graph.channels) # state updaters state_write_entries = [ - ChannelWriteEntry(key, None, skip_none=True) - if key == "__root__" - else ChannelWriteEntry( - key, RunnableCallable(_get_state_key, key=key, trace=False) + ( + ChannelWriteEntry(key, None, skip_none=True) + if key == "__root__" + else ChannelWriteEntry( + key, RunnableCallable(_get_state_key, key=key, trace=False) + ) ) for key in state_keys ] diff --git a/langgraph/prebuilt/agent_executor.py b/langgraph/prebuilt/agent_executor.py index 2e942002f..74a6156b8 100644 --- a/langgraph/prebuilt/agent_executor.py +++ b/langgraph/prebuilt/agent_executor.py @@ -5,6 +5,7 @@ from langchain_core.agents import AgentAction, AgentFinish from langchain_core.messages import BaseMessage from langgraph.graph import END, StateGraph +from langgraph.graph.state import CompiledStateGraph from langgraph.prebuilt.tool_executor import ToolExecutor from langgraph.utils import RunnableCallable @@ -39,7 +40,47 @@ def _get_agent_state(input_schema=None): return AgentState -def create_agent_executor(agent_runnable, tools, input_schema=None): +def create_agent_executor( + agent_runnable, tools, input_schema=None +) -> CompiledStateGraph: + """This is a helper function for creating a graph that works with LangChain Agents. + + Args: + agent_runnable (RunnableLike): The agent runnable. + tools (list): A list of tools to be used by the agent. + input_schema (dict, optional): The input schema for the agent. Defaults to None. + + Returns: + The `CompiledStateGraph` object. + + Examples: + + from langgraph.prebuilt import create_agent_executor + from langchain_openai import ChatOpenAI + from langchain import hub + from langchain.agents import create_openai_functions_agent + from langchain_community.tools.tavily_search import TavilySearchResults + + tools = [TavilySearchResults(max_results=1)] + + # Get the prompt to use - you can modify this! + prompt = hub.pull("hwchase17/openai-functions-agent") + + # Choose the LLM that will drive the agent + llm = ChatOpenAI(model="gpt-3.5-turbo-1106") + + # Construct the OpenAI Functions agent + agent_runnable = create_openai_functions_agent(llm, tools, prompt) + + app = create_agent_executor(agent_runnable, tools) + + inputs = {"input": "what is the weather in sf", "chat_history": []} + for s in app.stream(inputs): + print(list(s.values())[0]) + print("----") + + """ + if isinstance(tools, ToolExecutor): tool_executor = tools else: diff --git a/langgraph/prebuilt/chat_agent_executor.py b/langgraph/prebuilt/chat_agent_executor.py index 473d46cad..fbc254b96 100644 --- a/langgraph/prebuilt/chat_agent_executor.py +++ b/langgraph/prebuilt/chat_agent_executor.py @@ -8,6 +8,7 @@ from langchain_core.tools import BaseTool from langchain_core.utils.function_calling import convert_to_openai_function from langgraph.graph import END, StateGraph +from langgraph.graph.graph import CompiledGraph from langgraph.graph.message import add_messages from langgraph.prebuilt.tool_executor import ToolExecutor, ToolInvocation from langgraph.prebuilt.tool_node import ToolNode @@ -18,12 +19,14 @@ from langgraph.prebuilt.tool_node import ToolNode # We want steps to return messages to append to the list # So we annotate the messages attribute with operator.add class AgentState(TypedDict): + """The state of the agent.""" + messages: Annotated[Sequence[BaseMessage], add_messages] def create_function_calling_executor( model: LanguageModelLike, tools: Union[ToolExecutor, Sequence[BaseTool]] -): +) -> CompiledGraph: if isinstance(tools, ToolExecutor): tool_executor = tools tool_classes = tools.tools @@ -132,7 +135,33 @@ def create_function_calling_executor( def create_tool_calling_executor( model: LanguageModelLike, tools: Union[ToolExecutor, Sequence[BaseTool]] -): +) -> CompiledGraph: + """Creates a graph that works with a chat model that utilizes tool calling. + + Args: + model (LanguageModelLike): The chat model that supports OpenAI tool calling. + tools (Union[ToolExecutor, Sequence[BaseTool]]): A list of tools or a ToolExecutor instance. + + Returns: + Runnable: A compiled LangChain runnable that can be used for chat interactions. + + Examples: + + from langgraph.prebuilt import chat_agent_executor + from langchain_openai import ChatOpenAI + from langchain_community.tools.tavily_search import TavilySearchResults + from langchain_core.messages import HumanMessage + + tools = [TavilySearchResults(max_results=1)] + model = ChatOpenAI() + + app = chat_agent_executor.create_tool_calling_executor(model, tools) + + inputs = {"messages": [HumanMessage(content="what is the weather in sf")]} + for s in app.stream(inputs): + print(list(s.values())[0]) + print("----") + """ if isinstance(tools, ToolExecutor): tool_classes = tools.tools else: diff --git a/langgraph/pregel/__init__.py b/langgraph/pregel/__init__.py index 1d4031df3..810538fc1 100644 --- a/langgraph/pregel/__init__.py +++ b/langgraph/pregel/__init__.py @@ -303,6 +303,7 @@ class Pregel( ) def get_state(self, config: RunnableConfig) -> StateSnapshot: + """Get the current state of the graph.""" if not self.checkpointer: raise ValueError("No checkpointer set") @@ -323,6 +324,7 @@ class Pregel( ) async def aget_state(self, config: RunnableConfig) -> StateSnapshot: + """Get the current state of the graph.""" if not self.checkpointer: raise ValueError("No checkpointer set") @@ -343,6 +345,7 @@ class Pregel( ) def get_state_history(self, config: RunnableConfig) -> Iterator[StateSnapshot]: + """Get the history of the state of the graph.""" if not self.checkpointer: raise ValueError("No checkpointer set") @@ -364,6 +367,7 @@ class Pregel( async def aget_state_history( self, config: RunnableConfig ) -> AsyncIterator[StateSnapshot]: + """Get the history of the state of the graph.""" if not self.checkpointer: raise ValueError("No checkpointer set") @@ -559,6 +563,7 @@ class Pregel( interrupt_after_nodes: Optional[Sequence[str]] = None, debug: Optional[bool] = None, ) -> Iterator[Union[dict[str, Any], Any]]: + """Stream graph steps for a single input.""" config = ensure_config(config) callback_manager = get_callback_manager_for_config(config) run_manager = callback_manager.on_chain_start( @@ -970,6 +975,23 @@ class Pregel( debug: Optional[bool] = None, **kwargs: Any, ) -> Union[dict[str, Any], Any]: + """Run the graph with a single input and config. + + Args: + input: The input data for the graph. It can be a dictionary or any other type. + config: Optional. The configuration for the graph run. + stream_mode: Optional[str]. The stream mode for the graph run. Default is "values". + output_keys: Optional. The output keys to retrieve from the graph run. + input_keys: Optional. The input keys to provide for the graph run. + interrupt_before_nodes: Optional. The nodes to interrupt the graph run before. + interrupt_after_nodes: Optional. The nodes to interrupt the graph run after. + debug: Optional. Enable debug mode for the graph run. + **kwargs: Additional keyword arguments to pass to the graph run. + + Returns: + The output of the graph run. If stream_mode is "values", it returns the latest output. + If stream_mode is not "values", it returns a list of output chunks. + """ output_keys = output_keys if output_keys is not None else self.output_channels if stream_mode == "values": latest: Union[dict[str, Any], Any] = None @@ -1008,6 +1030,24 @@ class Pregel( debug: Optional[bool] = None, **kwargs: Any, ) -> Union[dict[str, Any], Any]: + """Asynchronously invoke the graph on a single input. + + Args: + input: The input data for the computation. It can be a dictionary or any other type. + config: Optional. The configuration for the computation. + stream_mode: Optional. The stream mode for the computation. Default is "values". + output_keys: Optional. The output keys to include in the result. Default is None. + input_keys: Optional. The input keys to include in the result. Default is None. + interrupt_before_nodes: Optional. The nodes to interrupt before. Default is None. + interrupt_after_nodes: Optional. The nodes to interrupt after. Default is None. + debug: Optional. Whether to enable debug mode. Default is None. + **kwargs: Additional keyword arguments. + + Returns: + The result of the computation. If stream_mode is "values", it returns the latest value. + If stream_mode is "chunks", it returns a list of chunks. + """ + output_keys = output_keys if output_keys is not None else self.output_channels if stream_mode == "values": latest: Union[dict[str, Any], Any] = None