gemini/agents/genai-experience-concierge/langgraph-demo/backend/notebooks/langgraph-agent.ipynb (397 lines of code) (raw):

{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": { "id": "f705f4be70e9" }, "outputs": [], "source": [ "# Copyright 2025 Google LLC\n", "#\n", "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", "# you may not use this file except in compliance with the License.\n", "# You may obtain a copy of the License at\n", "#\n", "# https://www.apache.org/licenses/LICENSE-2.0\n", "#\n", "# Unless required by applicable law or agreed to in writing, software\n", "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", "# See the License for the specific language governing permissions and\n", "# limitations under the License." ] }, { "cell_type": "markdown", "metadata": { "id": "40503295d0ef" }, "source": [ "# Constructing a LangGraphAgent" ] }, { "cell_type": "markdown", "metadata": { "id": "56af7aaf9a84" }, "source": [ "<table align=\"left\">\n", " <td style=\"text-align: center\">\n", " <a href=\"https://colab.research.google.com/github/GoogleCloudPlatform/generative-ai/blob/main/gemini/agents/genai-experience-concierge/langgraph-demo/backend/notebooks/langgraph-agent.ipynb\">\n", " <img width=\"32px\" src=\"https://www.gstatic.com/pantheon/images/bigquery/welcome_page/colab-logo.svg\" alt=\"Google Colaboratory logo\"><br> Open in Colab\n", " </a>\n", " </td>\n", " <td style=\"text-align: center\">\n", " <a href=\"https://console.cloud.google.com/vertex-ai/colab/import/https:%2F%2Fraw.githubusercontent.com%2FGoogleCloudPlatform%2Fgenerative-ai%2Fmain%2Fgemini%2Fagents%2Fgenai-experience-concierge%2Flanggraph-demo%2Fbackend%2Fnotebooks%2Flanggraph-agent.ipynb\">\n", " <img width=\"32px\" src=\"https://lh3.googleusercontent.com/JmcxdQi-qOpctIvWKgPtrzZdJJK-J3sWE1RsfjZNwshCFgE_9fULcNpuXYTilIR2hjwN\" alt=\"Google Cloud Colab Enterprise logo\"><br> Open in Colab Enterprise\n", " </a>\n", " </td>\n", " <td style=\"text-align: center\">\n", " <a href=\"https://console.cloud.google.com/vertex-ai/workbench/deploy-notebook?download_url=https://raw.githubusercontent.com/GoogleCloudPlatform/generative-ai/main/gemini/agents/genai-experience-concierge/langgraph-demo/backend/notebooks/langgraph-agent.ipynb\">\n", " <img src=\"https://www.gstatic.com/images/branding/gcpiconscolors/vertexai/v1/32px.svg\" alt=\"Vertex AI logo\"><br> Open in Vertex AI Workbench\n", " </a>\n", " </td>\n", " <td style=\"text-align: center\">\n", " <a href=\"https://github.com/GoogleCloudPlatform/generative-ai/blob/main/gemini/agents/genai-experience-concierge/langgraph-demo/backend/notebooks/langgraph-agent.ipynb\">\n", " <img width=\"32px\" src=\"https://www.svgrepo.com/download/217753/github.svg\" alt=\"GitHub logo\"><br> View on GitHub\n", " </a>\n", " </td>\n", "</table>\n", "\n", "<div style=\"clear: both;\"></div>\n", "\n", "<b>Share to:</b>\n", "\n", "<a href=\"https://www.linkedin.com/sharing/share-offsite/?url=https%3A//github.com/GoogleCloudPlatform/generative-ai/blob/main/gemini/agents/genai-experience-concierge/langgraph-demo/backend/notebooks/langgraph-agent.ipynb\" target=\"_blank\">\n", " <img width=\"20px\" src=\"https://upload.wikimedia.org/wikipedia/commons/8/81/LinkedIn_icon.svg\" alt=\"LinkedIn logo\">\n", "</a>\n", "\n", "<a href=\"https://bsky.app/intent/compose?text=https%3A//github.com/GoogleCloudPlatform/generative-ai/blob/main/gemini/agents/genai-experience-concierge/langgraph-demo/backend/notebooks/langgraph-agent.ipynb\" target=\"_blank\">\n", " <img width=\"20px\" src=\"https://upload.wikimedia.org/wikipedia/commons/7/7a/Bluesky_Logo.svg\" alt=\"Bluesky logo\">\n", "</a>\n", "\n", "<a href=\"https://twitter.com/intent/tweet?url=https%3A//github.com/GoogleCloudPlatform/generative-ai/blob/main/gemini/agents/genai-experience-concierge/langgraph-demo/backend/notebooks/langgraph-agent.ipynb\" target=\"_blank\">\n", " <img width=\"20px\" src=\"https://upload.wikimedia.org/wikipedia/commons/5/5a/X_icon_2.svg\" alt=\"X logo\">\n", "</a>\n", "\n", "<a href=\"https://reddit.com/submit?url=https%3A//github.com/GoogleCloudPlatform/generative-ai/blob/main/gemini/agents/genai-experience-concierge/langgraph-demo/backend/notebooks/langgraph-agent.ipynb\" target=\"_blank\">\n", " <img width=\"20px\" src=\"https://redditinc.com/hubfs/Reddit%20Inc/Brand/Reddit_Logo.png\" alt=\"Reddit logo\">\n", "</a>\n", "\n", "<a href=\"https://www.facebook.com/sharer/sharer.php?u=https%3A//github.com/GoogleCloudPlatform/generative-ai/blob/main/gemini/agents/genai-experience-concierge/langgraph-demo/backend/notebooks/langgraph-agent.ipynb\" target=\"_blank\">\n", " <img width=\"20px\" src=\"https://upload.wikimedia.org/wikipedia/commons/5/51/Facebook_f_logo_%282019%29.svg\" alt=\"Facebook logo\">\n", "</a>" ] }, { "cell_type": "markdown", "metadata": { "id": "dbfe0a3c85ab" }, "source": [ "| | |\n", "|-|-|\n", "|Author(s) | [Pablo Gaeta](https://github.com/pablofgaeta) |" ] }, { "cell_type": "markdown", "metadata": { "id": "80df1bbc5c57" }, "source": [ "## Overview\n", "\n", "This notebook demonstrates the necessary code to transform any LangGraph graph into a `LangGraphAgent` using the `concierge.langgraph_server` module.\n", "\n", "This is a useful interactive way to develop agents before deploying them on a server." ] }, { "cell_type": "markdown", "metadata": { "id": "faca4bb1709f" }, "source": [ "## Import dependencies" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "id": "d376d236bf4b" }, "outputs": [], "source": [ "import asyncio\n", "from typing import TypedDict\n", "import uuid\n", "\n", "from concierge.langgraph_server import langgraph_agent, schemas\n", "from langgraph import graph, types" ] }, { "cell_type": "markdown", "metadata": { "id": "fd56ca055bc6" }, "source": [ "## Define graph state schema and simple graph implementation" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "id": "9c8f32748aa9" }, "outputs": [], "source": [ "# State schema\n", "\n", "\n", "class State(TypedDict, total=False):\n", " id: str\n", "\n", "\n", "# Node functions\n", "\n", "\n", "async def set_id(state: State):\n", " new_id = state.get(\"id\")\n", " assert new_id is not None, \"must set ID\"\n", "\n", " await asyncio.sleep(1)\n", " return types.Command(update=State(id=new_id), goto=\"REVERSE_ID\")\n", "\n", "\n", "async def reverse_id(state: State):\n", " new_id = state.get(\"id\")\n", " assert new_id is not None, \"ID must be set before reversing\"\n", "\n", " await asyncio.sleep(1)\n", " return types.Command(update=State(id=new_id[::-1]))\n", "\n", "\n", "# Graph\n", "\n", "state_graph = graph.StateGraph(state_schema=State)\n", "state_graph.add_node(\"SET_ID\", set_id)\n", "state_graph.add_node(\"REVERSE_ID\", reverse_id)\n", "state_graph.set_entry_point(\"SET_ID\");" ] }, { "cell_type": "markdown", "metadata": { "id": "7cb6adb34f11" }, "source": [ "## Build a _stateful_ agent" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "id": "a49509c54b29" }, "outputs": [], "source": [ "basic_agent = langgraph_agent.LangGraphAgent(\n", " state_graph=state_graph,\n", " checkpointer_config=schemas.MemoryBackendConfig(),\n", ")" ] }, { "cell_type": "markdown", "metadata": { "id": "01c2cd4651a5" }, "source": [ "**Test**: Run a query in debug stream mode" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "id": "7b0721483f62" }, "outputs": [], "source": [ "async for chunk in basic_agent.stream(\n", " input=State(id=\"hello\"),\n", " config={\"configurable\": {\"thread_id\": uuid.uuid4().hex}},\n", " stream_mode=\"debug\",\n", "):\n", " print(chunk)" ] }, { "cell_type": "markdown", "metadata": { "id": "6cee145a454e" }, "source": [ "**Test**: Run a query in values mode (full state returned each time)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "id": "c368bf3c6b63" }, "outputs": [], "source": [ "async for chunk in basic_agent.stream(\n", " input=State(id=\"hello\"),\n", " config={\"configurable\": {\"thread_id\": uuid.uuid4().hex}},\n", " stream_mode=\"values\",\n", "):\n", " print(\"complete state\", \"=\", chunk)" ] }, { "cell_type": "markdown", "metadata": { "id": "b42173c19c6b" }, "source": [ "**Test**: Run a query in updates mode (only state updates returned by each node)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "id": "5702fb63eb29" }, "outputs": [], "source": [ "async for chunk in basic_agent.stream(\n", " input=State(id=\"hello\"),\n", " config={\"configurable\": {\"thread_id\": uuid.uuid4().hex}},\n", " stream_mode=\"updates\",\n", "):\n", " print(\"updates\", \"->\", chunk)" ] }, { "cell_type": "markdown", "metadata": { "id": "e65e2a213b30" }, "source": [ "**Test**: Run a query with a list of stream modes (yields stream mode and chunk data)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "id": "c30db9a8a393" }, "outputs": [], "source": [ "async for stream_mode, chunk in basic_agent.stream(\n", " input=State(id=\"hello\"),\n", " config={\"configurable\": {\"thread_id\": uuid.uuid4().hex}},\n", " stream_mode=[\"updates\"],\n", "):\n", " print(stream_mode, \"->\", chunk)" ] }, { "cell_type": "markdown", "metadata": { "id": "34b3574a9425" }, "source": [ "**Test**: Attempt a stateless query, fails since checkpointer requires thread ID. To run stateless queries, must build a stateless agent like the example in the next section." ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "id": "b91f9f8497a2" }, "outputs": [], "source": [ "async for stream_mode, chunk in basic_agent.stream(\n", " input=State(id=\"hello\"),\n", " config={\"configurable\": {\"thread_id\": uuid.uuid4().hex}},\n", " stream_mode=[\"updates\"],\n", "):\n", " print(stream_mode, \"->\", chunk)" ] }, { "cell_type": "markdown", "metadata": { "id": "c78f7af99ca9" }, "source": [ "## Build a _stateless_ agent" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "id": "693b95986c1a" }, "outputs": [], "source": [ "stateless_basic_agent = langgraph_agent.LangGraphAgent(\n", " state_graph=state_graph,\n", " checkpointer_config=None, # no checkpointer means it will only work with stateless requests\n", ")" ] }, { "cell_type": "markdown", "metadata": { "id": "397beba9ee29" }, "source": [ "**Test**: Run stateless run without threads" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "id": "9f02207bea72" }, "outputs": [], "source": [ "async for chunk in stateless_basic_agent.stream(\n", " input=State(id=\"hello\"),\n", " stream_mode=\"updates\",\n", "):\n", " print(\"complete state\", \"=\", chunk)" ] } ], "metadata": { "colab": { "name": "langgraph-agent.ipynb", "toc_visible": true }, "kernelspec": { "display_name": "Python 3", "name": "python3" } }, "nbformat": 4, "nbformat_minor": 0 }