结构化输出解析失败处理策略
langchain和LangGraph各自的数据契约实现机制有什么区别吗?还是都是一样的?
有区别。底层都可以用 Pydantic / TypedDict / JSON Schema 做类型约束,但解决的"契约边界"不同。
最简单的理解:
text
LangChain
→ 主要解决"LLM / Tool 输入输出的数据契约"
LangGraph
→ 主要解决"Agent 节点之间 State 的数据契约"
两者可以组合使用,但不是同一个东西。
1. LangChain:面向 LLM / Tool 的契约
LangChain 重点解决:
text
LLM
↓
Structured Output
↓
Pydantic
↓
结构化对象
Agent
↓
Tool
↓
Tool Input Schema
例如:
python
class SQLAnalysis(BaseModel):
cluster: str
database: str
sql: str
risk_level: Literal["LOW", "MEDIUM", "HIGH"]
然后:
python
structured_llm = llm.with_structured_output(SQLAnalysis)
这里的契约是:
text
LLM必须产生:
SQLAnalysis
Tool 也是类似:
python
class ExplainInput(BaseModel):
cluster: str
database: str
sql: str
python
@tool(args_schema=ExplainInput)
def mysql_explain(cluster, database, sql):
...
契约变成:
text
Agent → Tool
cluster: str
database: str
sql: str
所以 LangChain 的核心关注点是:
一个组件调用另一个组件时,输入输出的数据格式是什么。
2. LangGraph:面向 State 的契约
LangGraph 关注的是:
text
Node A
↓
State
↓
Node B
↓
State
↓
Node C
例如:
python
class DBAState(TypedDict):
user_query: str
cluster: str
database: str
slow_sql: str
analysis: SQLAnalysis | None
explain_result: dict | None
Graph:
text
START
↓
analyze
↓
explain
↓
optimize
↓
END
每个 Node 都围绕 State 工作:
python
def analyze(state: DBAState):
...
def explain(state: DBAState):
...
def optimize(state: DBAState):
...
所以 LangGraph 的契约核心是:
节点之间共享的 State 长什么样,以及每个节点读取/更新哪些 State 字段。
3. 两者最大的区别
可以直接这样记:
| LangChain | LangGraph | |
|---|---|---|
| 契约对象 | LLM、Tool、Chain | Node、State、Graph |
| 核心问题 | 输入/输出是什么 | 状态怎么传递 |
| 常用 Schema | Pydantic、JSON Schema | TypedDict、Pydantic、dataclass |
| Structured Output | 核心能力 | 通常借助 LangChain |
| Tool Schema | 核心能力 | Graph 中可以调用 |
| State | 不是核心 | 核心 |
| Retry | Runnable/组件层面 | Node/Graph层面 |
| HITL | 可参与实现 | 更适合编排 |
| 多节点数据流 | 较弱 | 核心 |
| 长流程状态 | 不负责核心编排 | 核心 |
所以:
text
LangChain
↓
"这个东西输入输出什么?"
LangGraph
↓
"这些东西之间怎么传递状态?"
4. 实际 DBA Agent 中,两者应该组合
例如你的慢 SQL 优化:
text
LangGraph
┌──────────────────────────────────┐
│ │
│ Node A │
│ pt-query-digest │
│ ↓ │
│ State │
│ ↓ │
│ Node B Node C │
│ LLM分析 EXPLAIN │
│ ↓ ↓ │
│ State ←──────────────┘ │
│ ↓ │
│ Node D │
│ 优化建议 │
│ │
└──────────────────────────────────┘
↑ ↑
│ │
LangChain LangChain
LLM Tool
具体来说:
text
LangChain
├── LLM Structured Output
├── Pydantic
├── Tool Schema
├── Tool Calling
└── Runnable
LangGraph
├── State
├── Node
├── Edge
├── Conditional Edge
├── Checkpoint
├── Retry
├── Interrupt/HITL
└── Loop
5. 最容易混淆的是:Pydantic 可以同时出现在两边
例如:
python
class SQLAnalysis(BaseModel):
cluster: str
database: str
sql: str
LangChain:
python
llm.with_structured_output(SQLAnalysis)
这是:
text
LLM Output Contract
而你也可以:
python
class DBAState(BaseModel):
user_query: str
analysis: SQLAnalysis
然后让 LangGraph State 使用它。
这是:
text
Graph State Contract
Schema 技术可以相同,但契约的语义不同。
6. DBA Agent 最推荐的架构
你可以把它理解成三层 Contract:
text
┌────────────────────────────────────┐
│ LangGraph State Contract │
│ │
│ Node A → State → Node B → State │
│ │
└────────────────┬───────────────────┘
│
┌────────┴────────┐
↓ ↓
LangChain LLM LangChain Tool
Contract Contract
↓ ↓
Pydantic Pydantic
Structured Output Tool Args Schema
也就是:
text
Agent Contract
│
┌─────────┴─────────┐
↓ ↓
Component Contract State Contract
↓ ↓
LangChain LangGraph
↓ ↓
Pydantic/JSON Schema TypedDict/Pydantic
再往下还有你前面提到的:
text
Business Contract
Security Contract
Runtime Contract
因此,LangChain 和 LangGraph 并不是各自有一套完全独立的数据契约技术。它们可以共用 Pydantic、JSON Schema 等 Schema 技术,但 LangChain 的契约主要约束"组件边界",LangGraph 的契约主要约束"状态和节点边界"。
对于你现在做的 DBA Agent,可以直接采用:
text
LangChain:
LLM Structured Output + Pydantic
Tool Input/Output + Pydantic
LangGraph:
State + TypedDict/Pydantic
Node输入/输出 + State
Retry/Error/HITL
业务层:
SQL Parser/AST + Business Validator
安全层:
RBAC/ACL + Guardrail
这套分层会比"所有东西都用 Pydantic"更清晰。