feat: upgrade LangGraph to 1.x and migrate deprecated APIs
- Bump langgraph from 0.4 to 1.0+, langgraph-supervisor from 0.0.12 to 0.0.30+ - Bump langchain-core, langchain-anthropic, langchain-openai to 1.x - Add langchain>=1.0 dependency for new create_agent location - Migrate create_react_agent -> create_agent (prompt -> system_prompt) - Fix create_supervisor positional arg to named agents= parameter - Replace AsyncMock checkpointer with InMemorySaver in tests (v1 type validation) - Update version references in README, ARCHITECTURE, eng-review-plan
This commit is contained in:
@@ -45,7 +45,7 @@ User message -> Chat UI -> FastAPI WebSocket -> LangGraph Supervisor -> Speciali
|
|||||||
| Component | Technology |
|
| Component | Technology |
|
||||||
|-----------|-----------|
|
|-----------|-----------|
|
||||||
| Backend | Python 3.11+, FastAPI |
|
| Backend | Python 3.11+, FastAPI |
|
||||||
| Agent orchestration | LangGraph 0.4+, langgraph-supervisor |
|
| Agent orchestration | LangGraph 1.x, langgraph-supervisor |
|
||||||
| Session state | PostgreSQL 16 + langgraph-checkpoint-postgres |
|
| Session state | PostgreSQL 16 + langgraph-checkpoint-postgres |
|
||||||
| LLM | Claude Sonnet 4.6 (configurable: OpenAI, Azure OpenAI, Google) |
|
| LLM | Claude Sonnet 4.6 (configurable: OpenAI, Azure OpenAI, Google) |
|
||||||
| Frontend | React 19, TypeScript, Vite |
|
| Frontend | React 19, TypeScript, Vite |
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from __future__ import annotations
|
|||||||
import logging
|
import logging
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from langgraph.prebuilt import create_react_agent
|
from langchain.agents import create_agent
|
||||||
from langgraph_supervisor import create_supervisor
|
from langgraph_supervisor import create_supervisor
|
||||||
|
|
||||||
from app.agents import get_tools_by_names
|
from app.agents import get_tools_by_names
|
||||||
@@ -59,11 +59,11 @@ def build_agent_nodes(
|
|||||||
f"Permission level: {agent_config.permission}."
|
f"Permission level: {agent_config.permission}."
|
||||||
)
|
)
|
||||||
|
|
||||||
agent_node = create_react_agent(
|
agent_node = create_agent(
|
||||||
model=llm,
|
model=llm,
|
||||||
tools=tools,
|
tools=tools,
|
||||||
name=agent_config.name,
|
name=agent_config.name,
|
||||||
prompt=system_prompt,
|
system_prompt=system_prompt,
|
||||||
)
|
)
|
||||||
agent_nodes.append(agent_node)
|
agent_nodes.append(agent_node)
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ def build_graph(
|
|||||||
prompt = SUPERVISOR_PROMPT.format(agent_descriptions=agent_descriptions)
|
prompt = SUPERVISOR_PROMPT.format(agent_descriptions=agent_descriptions)
|
||||||
|
|
||||||
workflow = create_supervisor(
|
workflow = create_supervisor(
|
||||||
agent_nodes,
|
agents=agent_nodes,
|
||||||
model=llm,
|
model=llm,
|
||||||
prompt=prompt,
|
prompt=prompt,
|
||||||
output_mode="full_history",
|
output_mode="full_history",
|
||||||
|
|||||||
@@ -6,12 +6,13 @@ requires-python = ">=3.11"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"fastapi>=0.115,<1.0",
|
"fastapi>=0.115,<1.0",
|
||||||
"uvicorn[standard]>=0.34,<1.0",
|
"uvicorn[standard]>=0.34,<1.0",
|
||||||
"langgraph>=0.4,<1.0",
|
"langgraph>=1.0,<2.0",
|
||||||
"langgraph-supervisor>=0.0.12,<1.0",
|
"langgraph-supervisor>=0.0.30,<1.0",
|
||||||
"langgraph-checkpoint-postgres>=3.0,<4.0",
|
"langgraph-checkpoint-postgres>=3.0,<4.0",
|
||||||
"langchain-core>=0.3,<1.0",
|
"langchain>=1.0,<2.0",
|
||||||
"langchain-anthropic>=0.3,<2.0",
|
"langchain-core>=1.0,<2.0",
|
||||||
"langchain-openai>=0.3,<1.0",
|
"langchain-anthropic>=1.0,<2.0",
|
||||||
|
"langchain-openai>=1.0,<2.0",
|
||||||
"langchain-google-genai>=2.1,<3.0",
|
"langchain-google-genai>=2.1,<3.0",
|
||||||
"psycopg[binary,pool]>=3.2,<4.0",
|
"psycopg[binary,pool]>=3.2,<4.0",
|
||||||
"pydantic>=2.10,<3.0",
|
"pydantic>=2.10,<3.0",
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ from typing import TYPE_CHECKING
|
|||||||
from unittest.mock import AsyncMock, MagicMock
|
from unittest.mock import AsyncMock, MagicMock
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
from langgraph.checkpoint.memory import InMemorySaver
|
||||||
|
|
||||||
from app.graph import build_agent_nodes, build_graph, classify_intent
|
from app.graph import build_agent_nodes, build_graph, classify_intent
|
||||||
from app.intent import ClassificationResult, IntentTarget
|
from app.intent import ClassificationResult, IntentTarget
|
||||||
@@ -34,20 +35,20 @@ class TestBuildGraph:
|
|||||||
mock_llm = MagicMock()
|
mock_llm = MagicMock()
|
||||||
mock_llm.bind_tools = MagicMock(return_value=mock_llm)
|
mock_llm.bind_tools = MagicMock(return_value=mock_llm)
|
||||||
mock_llm.with_structured_output = MagicMock(return_value=mock_llm)
|
mock_llm.with_structured_output = MagicMock(return_value=mock_llm)
|
||||||
mock_checkpointer = AsyncMock()
|
checkpointer = InMemorySaver()
|
||||||
|
|
||||||
graph = build_graph(sample_registry, mock_llm, mock_checkpointer)
|
graph = build_graph(sample_registry, mock_llm, checkpointer)
|
||||||
assert graph is not None
|
assert graph is not None
|
||||||
|
|
||||||
def test_graph_has_classifier_attached(self, sample_registry: AgentRegistry) -> None:
|
def test_graph_has_classifier_attached(self, sample_registry: AgentRegistry) -> None:
|
||||||
mock_llm = MagicMock()
|
mock_llm = MagicMock()
|
||||||
mock_llm.bind_tools = MagicMock(return_value=mock_llm)
|
mock_llm.bind_tools = MagicMock(return_value=mock_llm)
|
||||||
mock_llm.with_structured_output = MagicMock(return_value=mock_llm)
|
mock_llm.with_structured_output = MagicMock(return_value=mock_llm)
|
||||||
mock_checkpointer = AsyncMock()
|
checkpointer = InMemorySaver()
|
||||||
mock_classifier = MagicMock()
|
mock_classifier = MagicMock()
|
||||||
|
|
||||||
graph = build_graph(
|
graph = build_graph(
|
||||||
sample_registry, mock_llm, mock_checkpointer, intent_classifier=mock_classifier
|
sample_registry, mock_llm, checkpointer, intent_classifier=mock_classifier
|
||||||
)
|
)
|
||||||
assert graph.intent_classifier is mock_classifier
|
assert graph.intent_classifier is mock_classifier
|
||||||
assert graph.agent_registry is sample_registry
|
assert graph.agent_registry is sample_registry
|
||||||
@@ -56,9 +57,9 @@ class TestBuildGraph:
|
|||||||
mock_llm = MagicMock()
|
mock_llm = MagicMock()
|
||||||
mock_llm.bind_tools = MagicMock(return_value=mock_llm)
|
mock_llm.bind_tools = MagicMock(return_value=mock_llm)
|
||||||
mock_llm.with_structured_output = MagicMock(return_value=mock_llm)
|
mock_llm.with_structured_output = MagicMock(return_value=mock_llm)
|
||||||
mock_checkpointer = AsyncMock()
|
checkpointer = InMemorySaver()
|
||||||
|
|
||||||
graph = build_graph(sample_registry, mock_llm, mock_checkpointer)
|
graph = build_graph(sample_registry, mock_llm, checkpointer)
|
||||||
assert graph.intent_classifier is None
|
assert graph.intent_classifier is None
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ Smart Support 通过 MCP 协议连接内部系统,将自动化率提升到 60%+
|
|||||||
v
|
v
|
||||||
+--------+--------------------+
|
+--------+--------------------+
|
||||||
| LangGraph Supervisor | (Agent 编排 + 意图路由)
|
| LangGraph Supervisor | (Agent 编排 + 意图路由)
|
||||||
| langgraph-supervisor 0.0.12+|
|
| langgraph-supervisor 0.0.30+|
|
||||||
+--------+--------------------+
|
+--------+--------------------+
|
||||||
|
|
|
|
||||||
+----+----+----+----+
|
+----+----+----+----+
|
||||||
@@ -315,7 +315,7 @@ Agent 调用写操作工具
|
|||||||
|------|------|------|
|
|------|------|------|
|
||||||
| 语言 | Python 3.11+ | LangGraph/LangChain 生态首选语言, Agent 开发最成熟 |
|
| 语言 | Python 3.11+ | LangGraph/LangChain 生态首选语言, Agent 开发最成熟 |
|
||||||
| Web 框架 | FastAPI | 原生 async, WebSocket 支持, 性能优秀 |
|
| Web 框架 | FastAPI | 原生 async, WebSocket 支持, 性能优秀 |
|
||||||
| Agent 编排 | LangGraph v1.1 + langgraph-supervisor | 内置 supervisor 模式, 中间件支持, 不重复造轮子 |
|
| Agent 编排 | LangGraph 1.x + langgraph-supervisor | 内置 supervisor 模式, 中间件支持, 不重复造轮子 |
|
||||||
| MCP 集成 | langchain-mcp-adapters | MultiServerMCPClient 管理多 MCP 连接 |
|
| MCP 集成 | langchain-mcp-adapters | MultiServerMCPClient 管理多 MCP 连接 |
|
||||||
| 本地工具 | LangChain @tool 装饰器 | 简单 Python 函数即工具, 无 MCP 开销 |
|
| 本地工具 | LangChain @tool 装饰器 | 简单 Python 函数即工具, 无 MCP 开销 |
|
||||||
| 状态持久化 | PostgresSaver (langgraph-checkpoint-postgres v3.0.5) | 从第一天起用 PostgreSQL, 支持回放/分析查询 |
|
| 状态持久化 | PostgresSaver (langgraph-checkpoint-postgres v3.0.5) | 从第一天起用 PostgreSQL, 支持回放/分析查询 |
|
||||||
|
|||||||
@@ -104,8 +104,8 @@ smart-support/
|
|||||||
|
|
||||||
## Tech Stack
|
## Tech Stack
|
||||||
|
|
||||||
- Python 3.11+, FastAPI, LangGraph v1.1.0
|
- Python 3.11+, FastAPI, LangGraph 1.x (currently 1.1.6)
|
||||||
- langgraph-supervisor, langchain-mcp-adapters, langgraph-checkpoint-postgres v3.0.5
|
- langgraph-supervisor 0.0.31, langchain-mcp-adapters, langgraph-checkpoint-postgres v3.0.5
|
||||||
- React (frontend), PostgreSQL 16 (via Docker Compose)
|
- React (frontend), PostgreSQL 16 (via Docker Compose)
|
||||||
- Claude Sonnet 4.6 via `ChatAnthropic` (configurable via env)
|
- Claude Sonnet 4.6 via `ChatAnthropic` (configurable via env)
|
||||||
- pytest + FastAPI TestClient for backend tests
|
- pytest + FastAPI TestClient for backend tests
|
||||||
|
|||||||
Reference in New Issue
Block a user