第三章:LangChain Classic vs. 新版 LangChain —— 架构演进与迁移指南

系列:深入 LangChain ------ 从核心原理到生产实践

前置阅读第一章:LangChain 生态全景第二章:LangChain Core 深度剖析


学习目标

  • 理解 langchain-classiclibs/langchain/)与新版 langchainlibs/langchain_v1/)的本质区别
  • 掌握 Classic 中 Chain、Agent、Memory 三大核心模式的设计思想与局限性
  • 理解新版以 create_agent() + init_chat_model() + Middleware 为核心的精简架构
  • 建立从 Classic 到新版的完整迁移映射
  • 深入分析 Classic __init__.py 兼容层的延迟导入与废弃警告机制

3.1 两个时代:为什么会有两个 LangChain?

打开 LangChain 的 monorepo,你会发现一个有趣的现象:在 libs/ 目录下同时存在 langchain/(Classic)和 langchain_v1/(新版)两个独立的包。这并非代码组织的混乱,而是 LangChain 架构演进的自然产物。

复制代码
libs/
├── langchain/              # langchain-classic v1.0.3 ------ 遗留版本
│   └── langchain_classic/  # 40+ 子模块,Chain/Agent/Memory 为核心
├── langchain_v1/           # langchain v1.2.15 ------ 活跃开发版本
│   └── langchain/          # 7 个精简模块,LangGraph 为编排核心
└── core/                   # langchain-core v1.2.27 ------ 共享基础层
    └── langchain_core/     # 两个版本共同依赖的基础抽象

3.1.1 包命名与版本对照

维度 Classic(langchain-classic 新版(langchain
PyPI 包名 langchain-classic langchain
版本 v1.0.3(稳定维护) v1.2.15(活跃开发)
源码位置 libs/langchain/langchain_classic/ libs/langchain_v1/langchain/
Python 模块名 langchain_classic langchain
状态 仅修复关键 Bug,不再添加新功能 主力版本,持续迭代

理解这两个版本的关系是深入 LangChain 生态的关键。Classic 代表了 LangChain 的"第一代架构思想"------功能全包、Chain 为核心;新版代表了"第二代架构思想"------精简入口、图为核心。

3.1.2 依赖关系的根本差异

两个版本的依赖声明清晰地反映了架构理念的转变:

Classic 的 pyproject.toml (来源:libs/langchain/pyproject.toml):

toml 复制代码
dependencies = [
    "langchain-core>=1.2.19,<2.0.0",
    "langchain-text-splitters>=1.1.1,<2.0.0",
    "langsmith>=0.1.17,<1.0.0",
    "pydantic>=2.7.4,<3.0.0",
    "SQLAlchemy>=1.4.0,<3.0.0",     # ORM 框架 ------ 用于数据库交互
    "requests>=2.0.0,<3.0.0",       # HTTP 客户端 ------ 用于 API 调用
    "PyYAML>=5.3.0,<7.0.0",         # YAML 解析 ------ 用于配置和序列化
    "async-timeout>=4.0.0,<5.0.0; python_version < '3.11'",
]

新版的 pyproject.toml (来源:libs/langchain_v1/pyproject.toml):

toml 复制代码
dependencies = [
    "langchain-core>=1.2.10,<2.0.0",
    "langgraph>=1.1.5,<1.2.0",      # 图编排引擎 ------ 核心运行时
    "pydantic>=2.7.4,<3.0.0",
]

对比非常鲜明:

  • Classic 携带 7 个核心依赖(SQLAlchemy、requests、PyYAML 等),因为它试图在一个包内覆盖数据库交互、HTTP 请求、配置管理等全部能力
  • 新版仅 3 个核心依赖,将编排能力完全委托给 langgraph,其余功能下沉到 Partner 包

3.1.3 模块规模的量级差异

复制代码
langchain_classic/                    langchain/(新版)
├── agents/         (164 导出)         ├── agents/       (2 导出: create_agent, AgentState)
├── chains/         (87 导出)          ├── chat_models/  (2 导出: BaseChatModel, init_chat_model)
├── memory/         (26 导出)          ├── embeddings/   (2 导出: Embeddings, init_embeddings)
├── document_loaders/ (171 导出)       ├── messages/     (消息类型重导出)
├── callbacks/                         ├── tools/        (工具类型重导出)
├── text_splitter/                     └── rate_limiters/(2 导出)
├── embeddings/
├── llms/
├── output_parsers/
├── retrievers/
├── vectorstores/
├── utilities/
└── ... (40+ 子模块)                   共计 7 个模块

Classic 有 40+ 个子模块,导出数百个类和函数;新版只有 7 个模块,总共不到 20 个公开 API。这不是"功能缺失",而是设计哲学的根本转变 ------新版将自己定位为"精简入口层",把具体的功能实现分别交给 langchain-core(基础抽象)、langgraph(编排运行时)和 Partner 包(模型集成)。


3.2 Classic 核心模式深度解析

要理解为什么需要迁移,首先需要理解 Classic 的核心设计模式------Chain、Agent、Memory 三位一体的架构。

3.2.1 Chain 模式:线性组合的黄金年代

Chain 是 Classic 中最核心的抽象。它的设计思想很直观:将一系列操作串联起来,形成一条"链"。

Chain 基类 (来源:base.py):

python 复制代码
class Chain(RunnableSerializable[dict[str, Any], dict[str, Any]], ABC):
    """Abstract base class for creating structured sequences of calls to components."""

    memory: BaseMemory | None = None
    """Optional memory object."""
    callbacks: Callbacks = Field(default=None, exclude=True)
    verbose: bool = Field(default_factory=_get_verbosity)
    tags: list[str] | None = None
    metadata: dict[str, Any] | None = None

    @property
    @abstractmethod
    def input_keys(self) -> list[str]:
        """输入键列表"""

    @property
    @abstractmethod
    def output_keys(self) -> list[str]:
        """输出键列表"""

    @abstractmethod
    def _call(
        self,
        inputs: dict[str, Any],
        run_manager: CallbackManagerForChainRun | None = None,
    ) -> dict[str, str]:
        """执行链的核心逻辑"""

Chain 基类的设计有几个值得注意的特征:

  1. 继承 RunnableSerializable:虽然 Chain 是 Classic 的概念,但它已经桥接到了 Runnable 协议
  2. 字典驱动的 I/O :输入和输出都是 dict[str, Any],通过 input_keysoutput_keys 声明接口
  3. 内置 Memory 支持memory 字段直接嵌入基类,Chain 执行前后自动加载/保存记忆
  4. 回调系统集成:每次执行都会触发回调生命周期

LLMChain------最经典的 Chain 实现 (来源:llm.py):

python 复制代码
@deprecated(
    since="0.1.17",
    alternative="RunnableSequence, e.g., `prompt | llm`",
    removal="1.0",
)
class LLMChain(Chain):
    """Chain to run queries against LLMs."""

    prompt: BasePromptTemplate
    llm: Runnable[LanguageModelInput, str] | Runnable[LanguageModelInput, BaseMessage]
    output_key: str = "text"
    output_parser: BaseLLMOutputParser = Field(default_factory=StrOutputParser)
    return_final_only: bool = True
    llm_kwargs: dict = Field(default_factory=dict)

    @property
    def input_keys(self) -> list[str]:
        return self.prompt.input_variables

LLMChain 的核心工作流程是 Prompt → LLM → OutputParser------这正是后来 LCEL 管道 prompt | llm | parser 的前身。

Classic 的 Chain 生态------87 种 Chain 类型

Classic 的 chains/__init__.py 通过 _module_lookup 字典映射了 87 个 Chain 类型,涵盖了几乎所有常见的 LLM 应用模式:

类别 代表 Chain 数量 说明
文档组合 StuffDocumentsChainMapReduceDocumentsChainRefineDocumentsChain 6 处理长文档的四种策略
对话 ConversationChainConversationalRetrievalChain 2 带记忆的对话管理
LLM 应用 LLMChainLLMCheckerChainLLMMathChain 4 基础 LLM 调用链
检索问答 RetrievalQAQAWithSourcesChain 4 RAG 模式实现
路由 RouterChainMultiPromptChainMultiRetrievalQAChain 4 动态路由分发
序列 SequentialChainSimpleSequentialChainTransformChain 3 链式串联
图数据库 GraphQAChainGraphCypherQAChain 12+ 图数据库查询(重定向到 community)
其他 ConstitutionalChainHypotheticalDocumentEmbedder 10+ 特殊应用链

这种"为每个场景预制一个 Chain"的策略在早期很有效------开发者不需要理解底层原理,直接使用对应的 Chain 就能快速实现功能。但随着应用复杂度的提升,问题逐渐显现:

  • 组合爆炸:需要的 Chain 类型越来越多,维护成本指数增长
  • 灵活性不足:每个 Chain 的行为都是预设的,自定义需求需要继承重写
  • 字典接口的脆弱性input_keys/output_keys 缺乏类型安全,运行时才能发现键名错误

3.2.2 Agent 模式:决策循环的第一代实现

Classic 中的 Agent 系统由三个核心组件构成:AgentType(类型枚举)、Agent(决策逻辑)、AgentExecutor(执行循环)。

AgentType 枚举------9 种预定义 Agent 类型 (来源:agent_types.py):

python 复制代码
@deprecated(
    "0.1.0",
    message=AGENT_DEPRECATION_WARNING,
    removal="1.0",
)
class AgentType(str, Enum):
    """An enum for agent types."""

    ZERO_SHOT_REACT_DESCRIPTION = "zero-shot-react-description"
    """ReAct 模式:思考-操作-观察循环"""

    REACT_DOCSTORE = "react-docstore"
    """文档库 ReAct:Lookup + Search 双工具"""

    SELF_ASK_WITH_SEARCH = "self-ask-with-search"
    """自问自答:分解复杂问题为子问题"""

    CONVERSATIONAL_REACT_DESCRIPTION = "conversational-react-description"
    """对话式 ReAct"""

    CHAT_ZERO_SHOT_REACT_DESCRIPTION = "chat-zero-shot-react-description"
    """Chat 模型的零样本 ReAct"""

    CHAT_CONVERSATIONAL_REACT_DESCRIPTION = "chat-conversational-react-description"
    """Chat 模型的对话式 ReAct"""

    STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION = (
        "structured-chat-zero-shot-react-description"
    )
    """结构化 Chat:支持多输入工具"""

    OPENAI_FUNCTIONS = "openai-functions"
    """OpenAI 函数调用:利用原生 function calling"""

    OPENAI_MULTI_FUNCTIONS = "openai-multi-functions"
    """OpenAI 多函数调用"""

这 9 种类型涵盖了当时主流的 Agent 策略。但注意,整个枚举类都被标记为 @deprecated("0.1.0"),推荐迁移至 LangGraph。

AgentExecutor------Agent 执行引擎 (来源:agent.py):

python 复制代码
class AgentExecutor(Chain):
    """Agent that is using tools."""

    agent: BaseSingleActionAgent | BaseMultiActionAgent | Runnable
    tools: Sequence[BaseTool]
    return_intermediate_steps: bool = False
    max_iterations: int | None = 15
    max_execution_time: float | None = None
    early_stopping_method: str = "force"        # "force" 或 "generate"
    handle_parsing_errors: bool | str | Callable = False
    trim_intermediate_steps: int | Callable = -1

AgentExecutor 是 Classic Agent 系统的核心引擎。它的执行循环可以简化为:

复制代码
┌─────────────────────────────────────────────────┐
│              AgentExecutor 执行循环               │
│                                                   │
│  1. Agent.plan(inputs) → AgentAction | AgentFinish │
│     │                                              │
│     ├── AgentFinish → 返回最终结果                  │
│     │                                              │
│     └── AgentAction → 执行工具                      │
│           │                                        │
│           ├── tool.run(action.tool_input)           │
│           │                                        │
│           └── observation → 加入历史,回到步骤 1     │
│                                                   │
│  循环终止条件:                                     │
│  - AgentFinish                                     │
│  - 达到 max_iterations (15)                        │
│  - 超过 max_execution_time                         │
└─────────────────────────────────────────────────┘

AgentExecutor 的设计在当时是合理的,但也有明确的局限性:

  • 单一循环模式:只支持"思考-行动-观察"这一种循环结构,无法实现条件分支、并行执行
  • 状态管理原始 :中间步骤以 list[tuple[AgentAction, str]] 存储,无法做细粒度的状态控制
  • 错误恢复有限handle_parsing_errors 只处理输出解析错误,不支持工具执行失败的自动重试
  • 缺乏持久化:循环状态仅在内存中,无法跨请求保持

Classic Agent 的使用模式

典型的 Classic Agent 创建流程:

python 复制代码
# Classic 方式一:通过 initialize_agent 工厂函数
from langchain_classic.agents import initialize_agent, AgentType
from langchain_classic.tools import Tool

agent_executor = initialize_agent(
    tools=[search_tool, calculator_tool],
    llm=llm,
    agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
    verbose=True,
    max_iterations=10,
)
result = agent_executor.invoke({"input": "What is the weather in Beijing?"})

# Classic 方式二:手动组装
from langchain_classic.agents import ZeroShotAgent, AgentExecutor

prompt = ZeroShotAgent.create_prompt(tools=tools)
llm_chain = LLMChain(llm=llm, prompt=prompt)
agent = ZeroShotAgent(llm_chain=llm_chain, tools=tools)
executor = AgentExecutor(agent=agent, tools=tools)

Classic Agent 工具包------30+ Toolkits

Classic 还提供了大量预制的 Agent Toolkits,帮助开发者快速创建特定领域的 Agent:

类别 工具包 用途
数据分析 SQL Toolkit、Pandas Toolkit 数据库查询、数据框操作
开发工具 GitHub Toolkit、GitLab Toolkit 代码仓库操作
项目管理 Jira Toolkit、Slack Toolkit 工作流集成
通讯 Gmail Toolkit 邮件处理
API OpenAPI Toolkit 通用 API 交互
文件 File Management Toolkit 文件操作
搜索 VectorStore Toolkit 向量搜索

部分工具包后来被迁移到 langchain_experimental(如 create_csv_agentcreate_pandas_dataframe_agent),部分迁移到 langchain_community(如 create_sql_agent)。

3.2.3 Memory 模式:对话状态管理的探索

Classic 的 Memory 系统是一个独立的对话记忆管理框架,直接嵌入在 Chain 基类中。

BaseMemory 抽象

python 复制代码
@deprecated(
    since="0.3.3",
    removal="1.0.0",
    message="Please see the migration guide at: ..."
)
class BaseMemory(Serializable, ABC):
    """Memory 抽象基类"""

    @property
    @abstractmethod
    def memory_variables(self) -> list[str]:
        """返回内存提供的变量键"""

    @abstractmethod
    def load_memory_variables(self, inputs: dict[str, Any]) -> dict[str, Any]:
        """从内存加载变量"""

    @abstractmethod
    def save_context(self, inputs: dict[str, Any], outputs: dict[str, str]) -> None:
        """保存执行上下文到内存"""

    @abstractmethod
    def clear(self) -> None:
        """清空内存"""

Classic 提供了 26 种 Memory 实现,涵盖多种记忆策略:

策略 实现类 原理
全量缓冲 ConversationBufferMemory 存储完整对话历史
滑动窗口 ConversationBufferWindowMemory 只保留最近 k 轮对话
自动总结 ConversationSummaryMemory 用 LLM 总结旧对话
混合策略 ConversationSummaryBufferMemory 近期全量 + 远期总结
Token 计数 ConversationTokenBufferMemory 基于 Token 数量截断
实体追踪 ConversationEntityMemory 维护实体信息
向量检索 VectorStoreRetrieverMemory 通过语义相似度检索相关记忆
知识图谱 ConversationKGMemory 构建和查询知识图谱

Memory 系统的设计理念很超前,但在实践中暴露了几个问题:

  • 与 Chain 的紧耦合:Memory 嵌入 Chain 基类,在非 Chain 场景(如 LangGraph)中难以复用
  • 同步/异步割裂load_memory_variablesaload_memory_variables 需要分别实现
  • 状态管理局限:只能在 Chain 执行前后加载/保存,不支持中间步骤的细粒度状态管理

3.2.4 Document Loaders------171+ 种加载器

Classic 集成了 171+ 种文档加载器,覆盖了几乎所有数据源。但这些加载器全部通过 __getattr__ 动态重定向到 langchain_community

python 复制代码
# libs/langchain/langchain_classic/document_loaders/__init__.py
# 所有 loader 都从 langchain_community 动态导入
# 包括:WebBaseLoader, PyPDFLoader, CSVLoader, S3FileLoader,
# GoogleDriveLoader, TelegramChatLoader, ArxivLoader 等 171+ 种

这反映了 Classic 时代"大而全"的设计思路------一个包打天下。


3.3 新版架构:精简、专注、可组合

新版 LangChain(v1.2.15)的 __init__.py 只有一行有效代码:

python 复制代码
"""Main entrypoint into LangChain."""
__version__ = "1.2.15"

对比 Classic 那长达数百行的 __getattr__ 兼容层,新版的极简入口鲜明地体现了"精简入口"的设计理念。新版的全部公开 API 集中在 7 个模块中,核心能力可以用三个关键函数概括:

3.3.1 create_agent() ------ 一个函数取代整个 Agent 体系

新版用一个工厂函数 create_agent() 取代了 Classic 中 AgentType(9 种枚举)+ Agent(多种子类)+ AgentExecutor(执行引擎)+ initialize_agent()(工厂函数)的整套体系。

函数签名 (来源:factory.py):

python 复制代码
def create_agent(
    model: str | BaseChatModel,
    tools: Sequence[BaseTool | Callable[..., Any] | dict[str, Any]] | None = None,
    *,
    system_prompt: str | SystemMessage | None = None,
    middleware: Sequence[AgentMiddleware[StateT_co, ContextT]] = (),
    response_format: ResponseFormat[ResponseT] | type[ResponseT] | dict[str, Any] | None = None,
    state_schema: type[AgentState[ResponseT]] | None = None,
    context_schema: type[ContextT] | None = None,
    checkpointer: Checkpointer | None = None,
    store: BaseStore | None = None,
    interrupt_before: list[str] | None = None,
    interrupt_after: list[str] | None = None,
    debug: bool = False,
    name: str | None = None,
    cache: BaseCache[Any] | None = None,
) -> CompiledStateGraph[
    AgentState[ResponseT], ContextT, _InputAgentState, _OutputAgentState[ResponseT]
]:

关键设计决策

  1. 返回值是 LangGraph CompiledStateGraph:Agent 不再是一个独立的"执行引擎",而是一个编译后的状态图。这意味着你可以直接使用 LangGraph 的全部能力------中断、持久化、子图嵌套、流式执行。

  2. model 支持字符串格式"openai:gpt-4o" 内部会通过 init_chat_model() 自动解析为对应的 ChatModel 实例,省去了手动导入和实例化的步骤。

  3. middleware 替代了硬编码的 Agent 行为:Classic 中需要通过继承 Agent 子类来自定义行为,新版通过中间件组合实现,更加灵活。

  4. response_format 内置结构化输出 :支持 Pydantic 模型、ToolStrategyProviderStrategy 三种策略,无需额外包装。

  5. 原生持久化支持checkpointerstore 参数直接集成 LangGraph 的持久化能力,替代了 Classic 中笨重的 Memory 系统。

新版 Agent 的使用方式

python 复制代码
from langchain.agents import create_agent
from langchain.chat_models import init_chat_model

# 最简用法------3 行代码创建一个 Agent
model = init_chat_model("openai:gpt-4o")
agent = create_agent(model, tools=[search_tool, calculator_tool])
result = agent.invoke({"messages": [("human", "What is the weather?")]})

# 带中间件、持久化和结构化输出
from langchain.agents.middleware import (
    ModelFallbackMiddleware,
    SummarizationMiddleware,
    HumanInTheLoopMiddleware,
)
from pydantic import BaseModel

class WeatherReport(BaseModel):
    city: str
    temperature: float
    description: str

agent = create_agent(
    "anthropic:claude-sonnet-4-20250514",
    tools=[weather_tool],
    system_prompt="You are a weather assistant.",
    middleware=[
        ModelFallbackMiddleware(fallback_models=["openai:gpt-4o"]),
        SummarizationMiddleware(),
    ],
    response_format=WeatherReport,
    checkpointer=memory_saver,
)

3.3.2 init_chat_model() ------ 统一的模型初始化入口

新版的另一个核心函数是 init_chat_model(),它统一了所有 LLM 提供商的初始化方式。

内置提供商注册表 (来源:base.py):

python 复制代码
_BUILTIN_PROVIDERS: dict[str, tuple[str, str, Callable[..., BaseChatModel]]] = {
    "openai": ("langchain_openai", "ChatOpenAI", _call),
    "anthropic": ("langchain_anthropic", "ChatAnthropic", _call),
    "deepseek": ("langchain_deepseek", "ChatDeepSeek", _call),
    "google_vertexai": ("langchain_google_vertexai", "ChatVertexAI", _call),
    "google_genai": ("langchain_google_genai", "ChatGoogleGenerativeAI", _call),
    "cohere": ("langchain_cohere", "ChatCohere", _call),
    "fireworks": ("langchain_fireworks", "ChatFireworks", _call),
    "together": ("langchain_together", "ChatTogether", _call),
    "mistralai": ("langchain_mistralai", "ChatMistralAI", _call),
    "huggingface": ("langchain_huggingface", "ChatHuggingFace", _call),
    "groq": ("langchain_groq", "ChatGroq", _call),
    "ollama": ("langchain_ollama", "ChatOllama", _call),
    "xai": ("langchain_xai", "ChatXAI", _call),
    "perplexity": ("langchain_perplexity", "ChatPerplexity", _call),
    # ... 共 30+ 个提供商
}

使用方式对比

python 复制代码
# ---- Classic 方式:每个提供商需要单独导入 ----
from langchain_openai import ChatOpenAI
from langchain_anthropic import ChatAnthropic

model_openai = ChatOpenAI(model="gpt-4o", temperature=0.7)
model_anthropic = ChatAnthropic(model="claude-sonnet-4-20250514")

# ---- 新版方式:统一入口 ----
from langchain.chat_models import init_chat_model

model_openai = init_chat_model("openai:gpt-4o", temperature=0.7)
model_anthropic = init_chat_model("anthropic:claude-sonnet-4-20250514")

# 还支持自动推断提供商
model = init_chat_model("gpt-4o")          # 自动识别为 openai
model = init_chat_model("claude-sonnet-4-20250514")   # 自动识别为 anthropic

# 可配置模式------运行时动态切换
configurable_model = init_chat_model(
    configurable_fields=["model", "model_provider", "temperature"],
    config_prefix="main_",
)
# 在调用时指定具体模型
result = configurable_model.invoke(
    messages,
    config={"configurable": {"main_model": "gpt-4o", "main_model_provider": "openai"}}
)

init_chat_model() 的核心优势在于:

  1. 延迟导入:只在调用时加载对应的 Partner 包,避免不必要的依赖
  2. 字符串格式解析"provider:model-id" 格式简洁直观
  3. _ConfigurableModel 包装器 :通过 RunnableConfig 实现运行时模型切换

3.3.3 Middleware 系统------可组合的 Agent 行为扩展

新版引入了完整的 Middleware 系统,这是 Classic 中完全不存在的概念。Middleware 允许开发者在 Agent 执行循环的各个阶段插入自定义逻辑,无需修改核心代码。

AgentMiddleware 基类 (来源:types.py):

python 复制代码
class AgentMiddleware(Generic[StateT, ContextT, ResponseT]):
    """Base middleware class for an agent."""

    state_schema: type[StateT] = _DefaultAgentState
    tools: Sequence[BaseTool]

    @property
    def name(self) -> str:
        return self.__class__.__name__

    # 生命周期钩子(每个都有同步 + 异步版本)
    def before_agent(self, state, runtime) -> dict[str, Any] | None: ...
    def before_model(self, state, runtime) -> dict[str, Any] | None: ...
    def after_model(self, state, runtime) -> dict[str, Any] | None: ...
    def after_agent(self, state, runtime) -> dict[str, Any] | None: ...

    # 拦截钩子
    def wrap_model_call(self, request, handler) -> ModelResponse | AIMessage: ...
    def wrap_tool_call(self, request, handler) -> ToolMessage | Command: ...

Middleware 生命周期

复制代码
START
  ↓
before_agent          ← 全局初始化
  ↓
┌─────────────────────── Agent Loop ───────────────────────┐
│  before_model       ← 模型调用前(可修改消息/工具/提示词) │
│    ↓                                                       │
│  wrap_model_call    ← 拦截模型调用(重试/降级/缓存)        │
│    ↓                                                       │
│  [模型执行]                                                │
│    ↓                                                       │
│  after_model        ← 模型调用后(可修改结果)              │
│    ↓                                                       │
│  wrap_tool_call     ← 拦截工具调用(验证/mock/限流)        │
│    ↓                                                       │
│  [工具执行]                                                │
│    ↓                                                       │
│  (重复直到模型不再调用工具)                                 │
└──────────────────────────────────────────────────────────┘
  ↓
after_agent           ← 全局清理
  ↓
END

17 个内置 Middleware

新版在 langchain/agents/middleware/ 目录下提供了 17 个内置中间件:

类别 中间件 功能
模型管理 ModelRetryMiddleware 指数退避重试
ModelFallbackMiddleware 模型降级链
ModelCallLimitMiddleware 调用次数限制
工具管理 ToolRetryMiddleware 工具调用重试
ToolCallLimitMiddleware 工具调用限制
LLMToolEmulator LLM 模拟工具执行
LLMToolSelectorMiddleware LLM 驱动的工具选择
人机交互 HumanInTheLoopMiddleware 人类审批流
数据处理 SummarizationMiddleware 对话历史总结
PIIMiddleware PII 检测与脱敏
ContextEditingMiddleware 上下文编辑
文件/系统 FilesystemFileSearchMiddleware 文件搜索
ShellToolMiddleware Shell 命令执行
TodoListMiddleware TODO 管理

Middleware 的组合是嵌套式的 :第一个中间件是最外层,wrap_model_call 的处理器链通过 _chain_model_call_handlers() 组合,形成类似洋葱模型的执行顺序。

自定义 Middleware 示例

python 复制代码
from langchain.agents.middleware.types import AgentMiddleware, ModelRequest, ModelResponse

class LoggingMiddleware(AgentMiddleware):
    """记录每次模型调用的输入输出"""

    def wrap_model_call(self, request, handler):
        print(f"[LOG] Model input: {len(request.messages)} messages")
        response = handler(request)
        print(f"[LOG] Model output: {response.result[0].content[:100]}")
        return response

# 使用装饰器工厂------更简洁的写法
from langchain.agents.middleware.types import wrap_model_call

@wrap_model_call(name="rate_limiter")
def rate_limit_middleware(request, handler):
    import time
    time.sleep(1)  # 简单限速
    return handler(request)

3.3.4 AgentState------类型化的状态管理

新版用 TypedDict 定义 Agent 状态,替代了 Classic 中原始的字典 I/O:

AgentState 定义 (来源:types.py):

python 复制代码
class AgentState(TypedDict, Generic[ResponseT]):
    """State schema for the agent."""

    messages: Required[Annotated[list[AnyMessage], add_messages]]
    jump_to: NotRequired[Annotated[JumpTo | None, EphemeralValue, PrivateStateAttr]]
    structured_response: NotRequired[Annotated[ResponseT, OmitFromInput]]

三个字段各有深意:

  • messages :消息列表,使用 LangGraph 的 add_messages reducer。这是 Agent 的"记忆",每次执行都会追加新消息而非覆盖。
  • jump_to :流程控制字段,可以跳转到 'tools''model''end'。通过 EphemeralValue 注解标记为临时值,不会被持久化。
  • structured_response :结构化输出结果,支持泛型 ResponseT,通过 OmitFromInput 注解从输入 schema 中排除。

中间件可以通过 state_schema 属性扩展基础状态:

python 复制代码
class MyMiddlewareState(AgentState):
    """扩展状态,添加自定义字段"""
    retry_count: NotRequired[int]
    context_summary: NotRequired[str]

class MyMiddleware(AgentMiddleware):
    state_schema = MyMiddlewareState

    def before_model(self, state, runtime):
        # 访问扩展的状态字段
        if state.get("retry_count", 0) > 3:
            return {"jump_to": "end"}

3.4 架构对比:从宏观到微观

3.4.1 架构层次对比

Classic 的三层架构

复制代码
┌──────────────────────────────────────────────────────┐
│          langchain_classic (v1.0.3) 兼容入口层        │
│     __getattr__ 动态导入 + _warn_on_import 废弃警告   │
├──────────────────────────────────────────────────────┤
│                核心实现层(本地代码)                    │
│  ├── agents/       9 种 Agent + AgentExecutor 循环    │
│  ├── chains/       87 种 Chain 预制件                  │
│  ├── memory/       26 种 Memory 实现                   │
│  └── document_loaders/ 171+ 种加载器(→ community)    │
├──────────────────────────────────────────────────────┤
│              langchain_core (基础抽象)                  │
│              langchain_community (社区集成)             │
└──────────────────────────────────────────────────────┘

新版的精简架构

复制代码
┌──────────────────────────────────────────────────────┐
│              langchain (v1.2.15) 精简入口层             │
│  create_agent() + init_chat_model() + Middleware       │
├──────────────┬───────────────┬────────────────────────┤
│ langchain-core │   langgraph    │   Partner 包          │
│ (基础抽象)     │ (图编排引擎)    │ (模型/向量库集成)     │
└──────────────┴───────────────┴────────────────────────┘

3.4.2 核心概念映射表

Classic 概念 新版对应 迁移说明
AgentExecutor + Agent 子类 create_agent() 返回 LangGraph CompiledStateGraph
AgentType 枚举(9 种) 不再需要 create_agent() 自动处理工具调用策略
LLMChain LCEL 管道 `prompt model
SequentialChain / SimpleSequentialChain RunnableSequence(管道操作符 ` `)
RouterChain / MultiPromptChain RunnableBranch 或 LangGraph 条件边 声明式路由
BaseMemory(26 种实现) LangGraph Checkpointer + BaseStore 图级状态持久化
ConversationBufferMemory AgentState.messages + add_messages reducer 消息自动累积
ConversationSummaryMemory SummarizationMiddleware 中间件自动总结
手动错误处理 ModelFallbackMiddleware / ModelRetryMiddleware 声明式容错
initialize_agent(agent=AgentType.OPENAI_FUNCTIONS) create_agent(model, tools=...) 自动检测工具调用能力
Agent Toolkits(30+) 自定义工具 + Middleware 按需组合
document_loaders/(171+) 迁移到 langchain_community 不再由主包管理
handle_parsing_errors ToolRetryMiddleware 细粒度重试控制
max_iterations ModelCallLimitMiddleware / ToolCallLimitMiddleware 分别限制模型和工具调用次数

3.4.3 代码量对比

指标 Classic 新版
Python 文件数 1300+ ~30
核心依赖数 7 3
公开 API 数量 数百个 ~20
agents/__init__.py 导出 164 个 2 个
chains/__init__.py 导出 87 个 不存在
Agent 创建方式 initialize_agent() + AgentType + Agent 子类 + AgentExecutor create_agent()
模型初始化 每个 Provider 单独导入 init_chat_model("provider:model")
行为定制 继承 Agent/Chain 子类 Middleware 组合

3.5 Classic 兼容层:优雅的过渡设计

Classic 版本并没有简单地被弃用,而是通过精心设计的兼容层实现了平滑过渡。这个兼容层的设计值得深入分析。

3.5.1 __getattr__ 延迟导入机制

Classic 的 __init__.py(来源:init.py)使用 __getattr__ 实现模块级的动态导入:

python 复制代码
def __getattr__(name: str) -> Any:
    if name == "MRKLChain":
        from langchain_classic.agents import MRKLChain
        _warn_on_import(name, replacement="langchain_classic.agents.MRKLChain")
        return MRKLChain

    if name == "OpenAI":
        from langchain_community.llms import OpenAI
        _warn_on_import(name, replacement="langchain_community.llms.OpenAI")
        return OpenAI

    if name == "PromptTemplate":
        from langchain_core.prompts import PromptTemplate
        _warn_on_import(name, replacement="langchain_core.prompts.PromptTemplate")
        return PromptTemplate

    if name == "LLMBashChain":
        msg = (
            "This module has been moved to langchain-experimental. "
            "For more details: ..."
        )
        raise ImportError(msg)
    # ...

这个 __getattr__ 实现了三种重定向策略:

  1. 内部重定向 :从 langchain_classic 根级别重定向到子模块(如 MRKLChainlangchain_classic.agents
  2. 跨包重定向 :从 langchain_classic 重定向到 langchain_communitylangchain_core(如 OpenAIlangchain_community.llms
  3. 移除告知 :对已完全移除的模块抛出 ImportError 并告知迁移路径(如 LLMBashChainlangchain-experimental

3.5.2 _warn_on_import 废弃警告

python 复制代码
def _warn_on_import(name: str, replacement: str | None = None) -> None:
    """Warn on import of deprecated module."""
    from langchain_classic._api.interactive_env import is_interactive_env

    if is_interactive_env():
        # 在 Jupyter/IPython 中不显示警告
        return

    if replacement:
        warnings.warn(
            f"Importing {name} from langchain root module is no longer supported. "
            f"Please use {replacement} instead.",
            stacklevel=3,
        )

设计亮点:

  • 环境感知 :通过 is_interactive_env() 检测 Jupyter/IPython 环境,在交互式环境中静默不警告,避免在自动补全时触发大量警告
  • stacklevel=3 :让警告指向用户代码中的 import 语句,而非框架内部代码
  • 明确的替代方案:每个警告都告知具体的迁移路径

3.5.3 create_importer 通用导入工厂

Classic 的子模块(如 agents/__init__.pychains/__init__.py)使用更通用的 create_importer 工厂函数:

python 复制代码
# agents/__init__.py 的延迟导入
DEPRECATED_LOOKUP = {
    "create_json_agent": "langchain_community.agent_toolkits.json.base",
    "create_openapi_agent": "langchain_community.agent_toolkits.openapi.base",
    "create_sql_agent": "langchain_community.agent_toolkits.sql.base",
    "load_tools": "langchain_community.agent_toolkits.load_tools",
    # ...
}

DEPRECATED_CODE = [
    "create_csv_agent",              # → langchain_experimental
    "create_pandas_dataframe_agent", # → langchain_experimental
    "create_spark_dataframe_agent",  # → langchain_experimental
]

_import_attribute = create_importer(__package__, deprecated_lookups=DEPRECATED_LOOKUP)

def __getattr__(name: str) -> Any:
    if name in DEPRECATED_CODE:
        msg = f"{name} has been moved to langchain_experimental."
        raise ImportError(msg)
    return _import_attribute(name)

create_importer 的核心实现(来源:langchain_classic/_api/module_import.py)提供了:

  • 白名单验证 :只允许从 {langchain_community, langchain_core, langchain_classic} 导入
  • 缺失依赖提示 :当目标模块不存在时,自动提示安装 langchain-community
  • 内部调用检测 :通过 internal.is_caller_internal(depth=3) 避免对框架内部调用发出警告
  • 统一的废弃警告模板 :所有警告都遵循 since="0.1" / removal="1.0" 格式

3.5.4 废弃装饰器体系

Classic 使用统一的 @deprecated 装饰器标记所有废弃的类和函数:

python 复制代码
# 来源:langchain_classic/_api/deprecation.py
AGENT_DEPRECATION_WARNING = (
    "LangChain agents will continue to be supported, but it is recommended for new "
    "use cases to be built with LangGraph. LangGraph offers a more flexible and "
    "full-featured framework for building agents, including support for "
    "tool-calling, persistence of state, and human-in-the-loop workflows."
)

# 使用示例
@deprecated("0.1.0", message=AGENT_DEPRECATION_WARNING, removal="1.0")
class AgentType(str, Enum): ...

@deprecated("0.1.0", message=AGENT_DEPRECATION_WARNING, removal="1.0")
def initialize_agent(...) -> AgentExecutor: ...

@deprecated(since="0.1.17", alternative="RunnableSequence, e.g., `prompt | llm`", removal="1.0")
class LLMChain(Chain): ...

@deprecated(since="0.3.1", removal="1.0.0", message="Please see the migration guide at: ...")
class ConversationBufferMemory(BaseChatMemory): ...

废弃标记遵循统一的规则:

  • since:标注废弃的起始版本
  • removal:标注计划移除的版本(统一为 "1.0"
  • alternative:推荐的替代方案
  • message:自定义迁移指引

3.6 迁移实战:从 Classic 到新版

3.6.1 基础 LLM 调用迁移

Classic

python 复制代码
from langchain_classic.chains import LLMChain
from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI

prompt = PromptTemplate(
    input_variables=["topic"],
    template="Write a short poem about {topic}."
)
llm = ChatOpenAI(model="gpt-4o")
chain = LLMChain(llm=llm, prompt=prompt)
result = chain.invoke({"topic": "spring"})
print(result["text"])

新版(LCEL)

python 复制代码
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain.chat_models import init_chat_model

prompt = PromptTemplate(
    input_variables=["topic"],
    template="Write a short poem about {topic}."
)
model = init_chat_model("openai:gpt-4o")
chain = prompt | model | StrOutputParser()
result = chain.invoke({"topic": "spring"})
print(result)

关键变化:

  • LLMChain → LCEL 管道 prompt | model | parser
  • 不再需要显式导入 ChatOpenAI,使用 init_chat_model() 统一初始化
  • 输出从 result["text"] 变为直接的字符串

3.6.2 Agent 创建迁移

Classic

python 复制代码
from langchain_classic.agents import initialize_agent, AgentType
from langchain_classic.agents import ZeroShotAgent, AgentExecutor
from langchain_classic.chains import LLMChain
from langchain_openai import ChatOpenAI

# 方式一:使用工厂函数
llm = ChatOpenAI(model="gpt-4o")
agent_executor = initialize_agent(
    tools=[search_tool, calculator_tool],
    llm=llm,
    agent=AgentType.OPENAI_FUNCTIONS,
    verbose=True,
    max_iterations=15,
    handle_parsing_errors=True,
)
result = agent_executor.invoke({"input": "What's 2+2?"})

# 方式二:手动组装
prompt = ZeroShotAgent.create_prompt(tools=tools)
llm_chain = LLMChain(llm=llm, prompt=prompt)
agent = ZeroShotAgent(llm_chain=llm_chain, tools=tools)
executor = AgentExecutor(
    agent=agent,
    tools=tools,
    max_iterations=10,
    early_stopping_method="generate",
)

新版

python 复制代码
from langchain.agents import create_agent
from langchain.agents.middleware import ModelCallLimitMiddleware

agent = create_agent(
    "openai:gpt-4o",
    tools=[search_tool, calculator_tool],
    system_prompt="You are a helpful assistant.",
    middleware=[
        ModelCallLimitMiddleware(max_calls=15),
    ],
)
result = agent.invoke({"messages": [("human", "What's 2+2?")]})

关键变化:

  • initialize_agent() + AgentType + AgentExecutor → 单一的 create_agent()
  • max_iterationsModelCallLimitMiddleware(更精确的控制)
  • 输入从 {"input": "..."} 变为 {"messages": [...]}(消息驱动)
  • 不再需要选择 Agent 类型,create_agent() 自动处理工具调用

3.6.3 Memory 迁移

Classic

python 复制代码
from langchain_classic.memory import ConversationBufferMemory
from langchain_classic.chains import ConversationChain

memory = ConversationBufferMemory()
conversation = ConversationChain(
    llm=llm,
    memory=memory,
    verbose=True,
)
# 多轮对话
conversation.invoke({"input": "Hi, I'm Alice"})
conversation.invoke({"input": "What's my name?"})  # 记住了上下文

新版

python 复制代码
from langchain.agents import create_agent
from langgraph.checkpoint.memory import MemorySaver

# 使用 LangGraph Checkpointer 实现持久化
memory = MemorySaver()
agent = create_agent(
    "openai:gpt-4o",
    system_prompt="You are a helpful assistant.",
    checkpointer=memory,
)

# 多轮对话通过 thread_id 关联
config = {"configurable": {"thread_id": "user-123"}}
agent.invoke({"messages": [("human", "Hi, I'm Alice")]}, config)
agent.invoke({"messages": [("human", "What's my name?")]}, config)

关键变化:

  • ConversationBufferMemoryMemorySaver(LangGraph Checkpointer)
  • Memory 不再嵌入 Chain,而是通过配置传递
  • 多轮对话通过 thread_id 区分不同会话
  • 消息历史自动累积(add_messages reducer)

3.6.4 对话总结迁移

Classic

python 复制代码
from langchain_classic.memory import ConversationSummaryBufferMemory

memory = ConversationSummaryBufferMemory(
    llm=llm,
    max_token_limit=300,
)

新版

python 复制代码
from langchain.agents import create_agent
from langchain.agents.middleware import SummarizationMiddleware

agent = create_agent(
    "openai:gpt-4o",
    middleware=[
        SummarizationMiddleware(),  # 自动总结长对话
    ],
    checkpointer=memory_saver,
)

3.6.5 错误处理与降级迁移

Classic

python 复制代码
# 有限的错误处理能力
executor = AgentExecutor(
    agent=agent,
    tools=tools,
    handle_parsing_errors=True,  # 只处理解析错误
    max_iterations=10,
)

# 模型降级需要手动实现
try:
    result = primary_llm.invoke(prompt)
except Exception:
    result = fallback_llm.invoke(prompt)

新版

python 复制代码
from langchain.agents import create_agent
from langchain.agents.middleware import (
    ModelFallbackMiddleware,
    ModelRetryMiddleware,
    ToolRetryMiddleware,
)

agent = create_agent(
    "anthropic:claude-sonnet-4-20250514",
    tools=tools,
    middleware=[
        ModelRetryMiddleware(max_retries=3),     # 模型调用自动重试
        ModelFallbackMiddleware(                  # 模型降级链
            fallback_models=["openai:gpt-4o", "openai:gpt-4o-mini"],
        ),
        ToolRetryMiddleware(max_retries=2),      # 工具调用自动重试
    ],
)

3.6.6 结构化输出迁移

Classic

python 复制代码
from langchain_core.output_parsers import PydanticOutputParser
from pydantic import BaseModel

class Answer(BaseModel):
    answer: str
    confidence: float

parser = PydanticOutputParser(pydantic_object=Answer)
chain = prompt | llm | parser

新版

python 复制代码
from langchain.agents import create_agent
from pydantic import BaseModel

class Answer(BaseModel):
    answer: str
    confidence: float

# 直接传入 Pydantic 模型,自动选择最佳策略
agent = create_agent(
    "openai:gpt-4o",
    tools=tools,
    response_format=Answer,
)
result = agent.invoke({"messages": [("human", "What's the capital of France?")]})
# result["structured_response"] 是 Answer 实例

3.7 create_agent() 内部实现:图构建过程

理解 create_agent() 的内部实现有助于深入掌握新版架构。factory.py 是一个 1869 行的文件,其中 create_agent() 函数及其内部辅助函数构成了完整的图构建流程。

3.7.1 核心构建步骤

python 复制代码
# 简化的 create_agent 内部流程
def create_agent(model, tools, *, middleware, ...):
    # 1. 模型初始化
    if isinstance(model, str):
        model = init_chat_model(model)

    # 2. 系统消息处理
    system_message = SystemMessage(content=system_prompt) if system_prompt else None

    # 3. 中间件验证(去重检查)
    if len({m.name for m in middleware}) != len(middleware):
        raise AssertionError("Please remove duplicate middleware instances.")

    # 4. 中间件分类:哪些实现了 wrap_model_call / wrap_tool_call
    middleware_w_wrap_model_call = [
        m for m in middleware
        if m.__class__.wrap_model_call is not AgentMiddleware.wrap_model_call
    ]

    # 5. 组合处理器链
    wrap_model_call_wrapper = _chain_model_call_handlers(wrappers)
    wrap_tool_call_wrapper = _chain_tool_call_wrappers(wrappers)

    # 6. 创建 ToolNode
    tool_node = ToolNode(
        tools=available_tools,
        wrap_tool_call=wrap_tool_call_wrapper,
    ) if available_tools else None

    # 7. 构建 StateGraph
    graph = StateGraph(state_schema)
    graph.add_node("model", model_node)
    graph.add_node("tools", tool_node)

    # 8. 添加中间件节点和边
    for m in middleware:
        _add_middleware_edge(graph, m, ...)

    # 9. 添加条件边(模型 → 工具 / 模型 → 结束)
    graph.add_conditional_edges("model", _make_model_to_tools_edge(...))
    graph.add_conditional_edges("tools", _make_tools_to_model_edge(...))

    # 10. 编译并返回
    return graph.compile(
        checkpointer=checkpointer,
        store=store,
        interrupt_before=interrupt_before,
        interrupt_after=interrupt_after,
    )

3.7.2 图结构示意

复制代码
                    ┌────────────────┐
                    │     START      │
                    └───────┬────────┘
                            │
                 ┌──────────▼──────────┐
                 │   before_agent      │ (中间件节点,可选)
                 └──────────┬──────────┘
                            │
                 ┌──────────▼──────────┐
          ┌──────│     MODEL 节点      │◄─────────────┐
          │      │ (before_model →     │              │
          │      │  wrap_model_call →  │              │
          │      │  after_model)       │              │
          │      └──────────┬──────────┘              │
          │                 │                          │
          │    ┌────────────┼────────────┐            │
          │    │ 有工具调用   │  无工具调用  │            │
          │    ▼            ▼            │            │
          │  ┌──────────┐ ┌──────────┐  │            │
          │  │  TOOLS   │ │   END    │  │            │
          │  │(wrap_    │ │          │  │            │
          │  │tool_call)│ └──────────┘  │            │
          │  └────┬─────┘               │            │
          │       │                     │            │
          │       └─────────────────────┘            │
          │              回到 MODEL ─────────────────┘
          │
          │  (jump_to 流程控制)
          └──────────────► after_agent → END

这个图结构清晰地展示了新版 Agent 如何利用 LangGraph 的图能力替代了 Classic AgentExecutor 的简单循环。


3.8 迁移决策框架

3.8.1 什么时候应该迁移?

场景 建议
新项目 直接使用新版
使用 LLMChain 的简单应用 迁移到 LCEL 管道(改动最小)
使用 AgentExecutor 的 Agent 迁移到 create_agent()(获得中间件和持久化能力)
使用 ConversationBufferMemory 迁移到 LangGraph Checkpointer
使用 ConversationSummaryMemory 迁移到 SummarizationMiddleware
深度使用 chains/ 中的特殊 Chain 评估是否可以用 LCEL 或 LangGraph 替代
使用 document_loaders/ 直接从 langchain_community 导入

3.8.2 迁移的核心心智模型转换

从 Classic 到新版的迁移,本质上是以下心智模型的转换:

复制代码
Classic 思维:                    新版思维:
"我需要找到合适的 Chain 类"  →  "我用管道组合 Runnable"
"我需要选择合适的 Agent 类型" →  "我用 create_agent + 中间件"
"我需要选择合适的 Memory 类"  →  "我用 Checkpointer + Middleware"
"我需要找到预制的解决方案"    →  "我用基础原语按需组合"

这种转变反映了整个 LLM 应用开发领域的成熟:从"框架提供预制方案"到"框架提供组合原语",从"大而全"到"精简可组合"。


3.9 本章小结

维度 Classic(langchain-classic v1.0.3) 新版(langchain v1.2.15)
设计哲学 功能全包,预制方案优先 精简入口,组合原语优先
核心抽象 Chain + Agent + Memory create_agent() + Middleware + StateGraph
编排方式 SequentialChain / AgentExecutor 循环 LangGraph 状态图
状态管理 BaseMemory(链级内嵌) Checkpointer + BaseStore(图级持久化)
行为定制 继承子类重写 中间件组合
模型集成 每个 Provider 单独导入 init_chat_model("provider:model")
错误处理 handle_parsing_errors 布尔值 ModelRetryMiddleware + ModelFallbackMiddleware
人工介入 不支持 HumanInTheLoopMiddleware + interrupt_before/after
结构化输出 PydanticOutputParser(手动接入) response_format(内置支持)
兼容策略 __getattr__ 动态导入 + @deprecated 装饰器 N/A(全新设计)

Classic 版本完成了它的历史使命------降低 LLM 应用开发的入门门槛,让开发者能够快速构建原型。而新版则面向生产环境,提供更灵活、更可控、更可扩展的架构。两者之间通过精心设计的兼容层和废弃策略实现平滑过渡,这种演进方式本身就是优秀软件工程的范例。


下一章预告第四章:模型集成生态 ------ Partner 包架构与 init_chat_model 统一入口 将深入探讨 Partner 包的标准化架构、_BUILTIN_PROVIDERS 注册机制、Model Profiles 系统,以及如何创建自己的 Partner 集成。

相关推荐
BizViewStudio2 小时前
甄选 2026:AI 重构新媒体代运营行业的三大核心变革与落地路径
大数据·人工智能·新媒体运营·媒体
俊哥V2 小时前
AI一周事件 · 2026年4月8日至4月14日
人工智能·ai
GitCode官方3 小时前
G-Star Gathering Day 杭州站回顾
人工智能·开源·atomgit
宇擎智脑科技3 小时前
开源 AI Agent 架构设计对比:Python 单体 vs TypeScript 插件化
人工智能·openclaw·hermes agent
冷色系里的一抹暖调4 小时前
OpenClaw Docker部署避坑指南:服务启动成功但网页打不开?
人工智能·docker·容器·openclaw
曹牧4 小时前
自动编程AI落地方案‌
人工智能
天云数据4 小时前
Harness革命:企业级AI从“失控野马”到“价值引擎”的跃迁
人工智能
汽车仪器仪表相关领域4 小时前
NHVOC-70系列固定污染源挥发性有机物监测系统:精准破局工业VOCs监测痛点,赋能环保合规升级
大数据·人工智能·安全性测试
克里斯蒂亚诺·罗纳尔达4 小时前
智能体学习23——资源感知优化(Resource-Aware Optimization)
人工智能·学习