乐于分享
好东西不私藏

AI Agent 构建实战笔记(20260524)

AI Agent 构建实战笔记(20260524)

文章目录

    • 第一部分:基础认知 —— Agent 到底是什么?
      • 1.1 从 LLM 到 Agent
      • 1.2 核心概念澄清:Agent、Skill、Tool、MCP
    • 第二部分:深入 Function Calling 的底层机制
      • 2.1 Function Calling 本质
      • 2.2 LangChain 如何统一不同模型的差异
        • 工具定义的统一:用 `@tool` 装饰器
        • 响应解析的统一:全部转为 `AIMessage`
      • 2.3 LangGraph 的角色:流程编排,不是解析器
        • 💡 白话理解
        • 🧱 代码上怎么体现
        • 🚀 复杂任务才显出真价值
    • 第三部分:传统 Function Calling vs. MCP 架构
      • 3.1 传统方式:工具写死在 Agent 里
      • 3.2 现代方式:用 MCP 实现工具的解耦与标准化
      • 3.3 对比总结
    • 第四部分:Agent 的架构设计:从 MVP 到完整四层
      • 4.1 完整的四层架构
      • 4.1.1 什么是 ReAct 循环?
      • 4.1.2 四层架构的技术栈
      • 4.1.3 Skill 到底属于哪一层?
      • 4.1.4 人格提示词的两种加载方式
      • 4.2 从 MVP 开始:两层架构
        • MVP 是什么?
        • 最简代码示例(两层架构)
    • 第五部分:Skill(技能)的加载与决策
      • 5.1 Skill 的加载:渐进式披露
        • 渐进式披露的核心设计思想
      • 5.2 Skill 的决策:LLM 如何判断?
    • 第六部分:Skill 与 MCP 的协同工作流(完整示例)
      • 6.1 场景设定
      • 6.2 准备工作:定义工具和 Skill
      • 6.3 核心:用 LangGraph 组装 Agent
      • 6.4 完整的执行流程
      • 6.5 关键要点
    • 第七部分:Agent 的自进化 —— 实用简化方案
      • 7.1 进化思路
      • 7.2 简化版设计
        • 核心规则
        • 所需工具
      • 7.3 完整端到端实现
      • 7.4 执行流程与进化演示
      • 7.5 与完整方案的对比

第一部分:基础认知 —— Agent 到底是什么?

1.1 从 LLM 到 Agent

单纯的 LLM 就像一个博学的书呆子,只能一问一答,没有状态,不能执行动作。Agent = LLM + 工具 + 记忆 + 规划能力,它能自主拆解任务、调用工具、记住上下文,并完成真实世界的操作。

1.2 核心概念澄清:Agent、Skill、Tool、MCP

为了避免混淆,我们只使用以下四个明确定义的术语:

  • Agent (智能体)
    :负责规划、决策、调度的“大脑”。
  • Skill (技能)
    特指知识型的 .md 文件。它是教 Agent “怎么做”的操作手册(流程、规范、最佳实践),LLM需要阅读并理解它。
  • Tool (工具)
    特指可执行的函数/方法。它是 Agent 完成具体动作的“手脚”(如查天气、发邮件、操作数据库),可以通过本地函数或 MCP Server 暴露。
  • MCP (模型上下文协议)
    :连接 Agent 和外部工具的标准化协议。它为 Agent 提供了“即插即用”调用各种工具的能力。同时,它也可以作为“传输管道”,被用来读取 Skill 文件。

协同公式:用户任务 → Agent 决策 → (需要流程指导时)通过 skill_load 工具加载 Skill 手册 → (需要执行动作时)通过 MCP 调用 Tool → 执行并反馈。


第二部分:深入 Function Calling 的底层机制

2.1 Function Calling 本质

它不是 LLM 暴露给外部的“接口”,而是 LLM 被训练出的结构化响应能力 当你把 tools 参数(包含工具名称、描述和参数的 JSON Schema)传给 API 后,LLM 会返回一个特殊的 JSON 对象,例如:

{  "tool_name": "get_weather",  "arguments": {"city": "北京"}}

你的代码拿到这个 JSON,去执行真正的函数,再把结果返回给 LLM 生成最终回复。

代码流程(以 OpenAI GPT-4o 为例)

  1. 定义工具,传给 API
tools = [{    "type""function",    "function": {        "name""get_weather",        "description""获取指定城市的天气",        "parameters": {            "type""object",            "properties": {"city": {"type""string"}},            "required": ["city"]        }    }}]response = openai.chat.completions.create(    model="gpt-4o",    messages=[{"role""user""content""东京天气怎么样?"}],    tools=tools)
  1. LLM 返回调用指令(不执行函数)
msg = response.choices[0].message# msg.tool_calls 中包含 function.name 和 arguments(JSON 字符串)
  1. 你的代码执行真正的函数
import jsonargs = json.loads(msg.tool_calls[0].function.arguments)result = get_weather(args["city"])  # 你写的真实函数
  1. 将结果返回给 LLM 生成最终回复
final = openai.chat.completions.create(    model="gpt-4o",    messages=[        {"role""user""content""东京天气怎么样?"},        msg,        {"role""tool""tool_call_id": msg.tool_calls[0].id"content": result}    ])

本质:LLM 只输出 JSON 指令,真正执行全靠你的代码。LangChain 等框架将这个循环自动化了。

2.2 LangChain 如何统一不同模型的差异

LangChain 通过 模型适配器(Model Integration) 将不同厂商的差异封装起来,开发者只需用一套标准格式定义工具,剩下的转换全自动完成。

工具定义的统一:用 @tool 装饰器

你只需写一个 Python 函数并加上装饰器,LangChain 会自动为不同模型生成对应的 Schema:

from langchain_core.tools import tool@tooldef get_weather(city: str) -> str:    """获取指定城市的天气信息"""    return f"{city}:晴,25°C"

当你选择不同模型时,LangChain 内部会将其转换为:

模型
转换后的格式
OpenAI{"type": "function", "function": {"name": "get_weather", "description": "...", "parameters": {...}}}
Anthropic{"name": "get_weather", "description": "...", "input_schema": {...}}
Google Gemini{"name": "get_weather", "description": "...", "parameters": {...}}
 (放入 tools.functionDeclarations)

响应解析的统一:全部转为 AIMessage

无论哪个模型返回的原始响应,LangChain 都会将其解析为统一的 AIMessage 对象:

from langchain_core.messages import AIMessage# 所有模型的响应最终都变成这种标准格式ai_msg = AIMessage(    content="",  # 如果调用了工具,content 可为空    tool_calls=[{        "name""get_weather",        "args": {"city""北京"},        "id""call_xxx"    }])

开发者只要检查 ai_msg.tool_calls 即可,无需关心底层是 OpenAI 的 message.tool_calls 还是 Anthropic 的 content[0].tool_use

一句话总结:你用一套 @tool 定义,LangChain 负责“翻译”成各模型的“方言”,并把各模型的“方言回复”统一解析成标准的 AIMessage

2.3 LangGraph 的角色:流程编排,不是解析器

💡 白话理解

把 Agent 想象成一场舞台剧:

  • 演员
     = LLM(负责思考和说话)
  • 道具组
     = LangChain(负责递工具、翻译响应)
  • 导演
     = LangGraph(指挥流程:谁上场、什么时候切换)

LangGraph 是导演,它不管台词怎么念(那是 LangChain 的事),只管“现在轮到谁上场”和“下一步去哪”。invoke 就是导演喊的那声“开机!”,整场戏自动按排练跑完。

🧱 代码上怎么体现

简单任务(一问一调一回):你原本需要手动写 while 循环来调度 LLM 和工具:

response = llm.invoke(user_input)while response.has_tool_calls:    result = execute_tool(...)    response = llm.invoke(result)

用 LangGraph 后,你把“角色”和“切换规则”定义成图,然后一声 invoke,它自动循环:

from langgraph.graph import StateGraph, ENDworkflow = StateGraph(dict)workflow.add_node("agent", call_llm)workflow.add_node("tools", call_tool)workflow.add_conditional_edges("agent", should_continue, {"tools""tools""end": END})workflow.add_edge("tools""agent")app = workflow.compile()result = app.invoke({"input""查天气"})

你不再需要自己写 while,LangGraph 在后台自动管理循环和跳转。

🚀 复杂任务才显出真价值

当任务涉及多步判断、人工确认时,手动 while + if-else 会变得混乱且难以维护。场景:“查北京天气,如果下雨就给老板发邮件提醒(发前需要用户确认)”

手动实现需要状态变量和一堆分支:

step = "call_weather"while True:    if step == "call_weather": ...    elif step == "check_rain": ...    elif step == "send_email": ...

每增加一个步骤,就要多一个 elif,逻辑纠缠。

LangGraph 实现:把每个步骤定义成独立节点,边定义路由,流程如蓝图般清晰:

workflow.add_node("weather", call_weather)workflow.add_node("after_weather", after_weather)workflow.add_node("wait_human", wait_for_human)workflow.add_node("send_email", send_email)workflow.add_conditional_edges("after_weather", lambda s: "wait_human" if "雨" in s else END)workflow.add_conditional_edges("wait_human", lambda s: "send_email" if user_says_yes else END)workflow.add_edge("send_email", END)

修改流程只需增删节点或改连线,不影响现有节点逻辑。

核心差别:手动 while 让流程和业务逻辑耦合,LangGraph 把流程变成可独立维护的“蓝图”,复杂任务下优势巨大。


第三部分:传统 Function Calling vs. MCP 架构

3.1 传统方式:工具写死在 Agent 里

  • 工具定义
    :在代码中硬编码 JSON Schema。
  • 调用逻辑
    :手动解析 LLM 的 tool_calls 并 if-else 判断执行哪个函数。
  • 缺点
    :工具和 Agent 强耦合,新增工具要改代码、重启服务,无法复用。

代码示例(OpenAI 原生调用,工具与 Agent 紧耦合)

import openai, json# 1. 硬编码工具定义tools = [{    "type""function",    "function": {        "name""get_weather",        "description""获取指定城市的天气",        "parameters": {            "type""object",            "properties": {"city": {"type""string"}},            "required": ["city"]        }    }}]# 2. Agent 调用response = openai.ChatCompletion.create(    model="gpt-4o",    messages=[{"role""user""content""北京天气?"}],    tools=tools)# 3. 手动解析与执行msg = response.choices[0].messageif msg.tool_calls:    tool_call = msg.tool_calls[0]    args = json.loads(tool_call.function.arguments)    if tool_call.function.name == "get_weather":        result = get_weather(args["city"])  # 本地函数    # ... 更多工具需要更多 if-else

⚠️ 想加一个“发邮件”工具?你得修改 tools 列表,增加 elif 分支,然后重启服务。

3.2 现代方式:用 MCP 实现工具的解耦与标准化

  • 工具定义
    :在独立的 MCP Server 中实现,通过 list_tools() 动态获取。
  • Agent
    :作为 MCP Client 连接 Server,自动加载工具清单,统一用 function calling 格式发给 LLM。
  • 优点
    :工具热插拔、多 Agent 复用、统一安全治理。

代码示例(MCP Server + Agent 分离)

① MCP Server(tool_server.py)—— 工具定义与 Agent 解耦

from fastapi import FastAPIfrom fastapi_mcp import FastApiMCPapp = FastAPI()@app.get("/weather/{city}", operation_id="get_weather")async def get_weather(city: str):    return {"city": city, "weather""晴""temperature""25°C"}mcp = FastApiMCP(app, name="工具箱", base_url="http://localhost:8000")mcp.mount()  # 所有端点自动暴露为 MCP 工具

② Agent 侧(agent.py)—— 动态发现与调用

from langchain_mcp_adapters.client import MCPClientfrom langchain.agents import create_openai_tools_agentasync def main():    client = MCPClient(server_url="http://localhost:8000/mcp")    tools = await client.load_tools()          # 动态获取,无需硬编码    agent = create_openai_tools_agent("gpt-4o", tools, system_prompt="你是助手")    # ... 运行 agent

✅ 新增工具?只需在 MCP Server 上加一个端点,Agent 零改动即可自动发现。

3.3 对比总结

对比维度
传统 Function Calling
MCP 方式
工具定义位置
嵌在 Agent 代码中
独立 MCP Server
新增工具
改代码 + 重启
动态发现,无需重启 Agent
复用性
低,紧耦合
高,多 Agent 共享
安全治理
分散实现
MCP Server 层统一控制

第四部分:Agent 的架构设计:从 MVP 到完整四层

4.1 完整的四层架构

1. 大脑层 (LLM + 人格)2. 记忆与知识层 (短期/长期记忆、RAG, Skill)3. 规划与调度层 (ReAct 循环、任务编排)4. 工具/身体层 (MCP 工具、本地函数)

这是从真实产品中抽象出的通用模型,得到了社区和工业界的普遍认可。几乎所有 Agent 都可以映射到这四层,实际落地时会根据场景“剪裁、合并或强化”。

4.1.1 什么是 ReAct 循环?

ReAct = Reasoning + Acting(推理 + 行动),是目前 Agent 最主流的推理模式。

其核心是让 LLM 在解决问题时,严格按照 “思考 → 行动 → 观察 → 再思考…” 的循环进行,直到任务完成。

  • Thought (思考)
    :当前目标是什么?需要什么信息?应该用哪个工具?
  • Action (行动)
    :调用具体工具(如查天气、计算器)。
  • Observation (观察)
    :工具返回了什么结果?
  • Final Answer (最终答案)
    :根据观察结果,生成给用户的回复。

当你用 LangChain 或 LangGraph 创建 Agent 并开启 verbose=True,后台输出的正是这个循环过程。

4.1.2 四层架构的技术栈

架构层
常见技术栈
说明
1. 大脑层LLM API
: OpenAI, Anthropic, Gemini, 本地模型 (vLLM, Ollama)人格加载: 硬编码 system_prompt(MVP)或 persona.md 动态加载(正式)
负责“思考”。人格也可当作特殊 Skill。
2. 记忆与知识层短期记忆
: 对话历史列表长期记忆: 向量数据库 (Chroma, Pinecone, Milvus) + 嵌入模型知识库(RAG): LangChain/LlamaIndex技能(Skill): Markdown 文件 + 渐进式披露
为大脑提供上下文。Skill (.md) 属于这一层
3. 规划与调度层Agent 框架
: LangGraph (图编排), CrewAI (多Agent协作), AutoGen (对话驱动)推理模式: ReAct, Plan-and-Execute
负责流程骨架。
4. 工具/身体层工具定义
: MCP Server (推荐), 本地 @tool 函数工具调用: Function Calling集成langchain-mcp-adapters
负责执行具体动作。

4.1.3 Skill 到底属于哪一层?

Skill (.md 文件) 属于第二层:记忆与知识层。它为 LLM 提供“流程性知识”,与 RAG 文档的“陈述性知识”互补。而用来加载 Skill 的 skill_load 工具本身属于第四层。

4.1.4 人格提示词的两种加载方式

方式
做法
适用场景
硬加载
直接在代码里写 system_prompt = "你是一个..."
MVP 阶段、快速验证
动态加载
把人格写成一个 persona.md 文件,像 Skill 一样在启动时通过 load_skill("persona") 加载
正式项目、需要灵活切换人格

推荐做法:把人格当作一个特殊的 Skill,统一走渐进式披露通道。

  • 架构统一
    :人格和普通 Skill 用同一套机制管理。
  • 灵活修改
    :改人格只需编辑 .md 文件,不用动代码。
  • 可进化
    :甚至可以让 Agent 自己更新人格(如 skill_update("persona", ...))。

在 MVP 示例(4.2 节)中我们用了硬加载,那是为了最快跑通。正式搭建时建议改用动态加载。

4.2 从 MVP 开始:两层架构

MVP 是什么?

MVP = Minimum Viable Product(最小可行产品)。用最少的代码、最简单的架构,先把核心功能跑通,验证想法可行后再逐步加东西。

最简代码示例(两层架构)

一个能查天气的 Agent,只用 Python + OpenAI API,不依赖任何框架:

import openai, json# ========== 第一层:工具(本地函数) ==========def get_weather(city: str) -> str:    """查询天气的工具函数"""    weather_data = {"北京""晴,25°C""东京""多云,18°C"}    return weather_data.get(city, "未找到该城市天气")# 手动定义工具 schema(LLM 看的"菜单")tools = [{    "type""function",    "function": {        "name""get_weather",        "description""查询指定城市的天气",        "parameters": {            "type""object",            "properties": {"city": {"type""string""description""城市名称"}},            "required": ["city"]        }    }}]# ========== 第二层:大脑 + 规划 ==========def agent(user_input: str) -> str:    # 1. 加载人格 + 发起第一次 LLM 调用    messages = [        {"role""system""content""你是一个乐于助人的助手。"},        {"role""user""content": user_input}    ]    response = openai.chat.completions.create(        model="gpt-4o", messages=messages, tools=tools    )    msg = response.choices[0].message    # 2. ReAct 循环:检查 LLM 是否想调用工具    while msg.tool_calls:        for tool_call in msg.tool_calls:            args = json.loads(tool_call.function.arguments)            result = get_weather(**args)            messages.append(msg)            messages.append({"role""tool""tool_call_id": tool_call.id"content": result})        response = openai.chat.completions.create(model="gpt-4o", messages=messages, tools=tools)        msg = response.choices[0].message    return msg.contentprint(agent("北京今天天气怎么样?"))# 输出:北京今天天气晴朗,气温25°C。

这个不到 40 行的代码包含了 Agent 的所有核心要素:

要素
对应代码
大脑 (LLM)openai.chat.completions.create()
人格system: "你是一个乐于助人的助手。"
工具get_weather()
 函数 + tools schema
规划 (ReAct 循环)while msg.tool_calls:
 循环
记忆(短期)messages
 列表累积对话历史

何时升级?

  • 工具数量 > 5 且需复用 → 引入 MCP 工具层
  • 多步推理、条件分支 → 引入 LangGraph 规划层
  • 跨会话记忆 → 引入 记忆层

第五部分:Skill(技能)的加载与决策

5.1 Skill 的加载:渐进式披露

Skill 是知识型文件(.md),内容可能很长。为解决上下文窗口问题,必须采用 渐进式披露,按需分层加载:

层级
内容
何时加载
大小
L1 元数据
技能名称 + 一句话描述
启动时加载
~100 tokens/个
L2 核心指令
完整的 SKILL.md 正文
LLM 决定使用后按需加载
<5000 tokens/个
L3 资源
引用的脚本、文档等
按需进一步加载
不定

渐进式披露的核心设计思想

不是提前把所有技能内容塞给 LLM,而是把“查询技能目录”和“加载指定技能”这两个能力本身,作为工具(Tool)暴露给 LLM。 LLM 就像拿着一张菜单(list_skills 返回的技能名称+简介),想吃哪道菜再叫服务员去后厨拿完整的菜谱(load_skill 返回 .md 全文)。

启动时:LLM 只知道有 list_skills 工具,不知道任何技能内容(0 token)用户提问后:LLM 主动调用 list_skills → 拿到目录(L1,~100 tokens/个)决定使用后:LLM 调用 load_skill → 拿到完整手册(L2,只加载一个)

整个过程完全由 LLM 自主决策,加载技能本身也是 function calling 的一种。这就是渐进式披露能与 MCP 工具无缝融合的根本原因。

5.2 Skill 的决策:LLM 如何判断?

  1. 语义匹配(主要方式)
    :LLM 根据用户意图和 Skill 元数据描述的匹配度自主决策。
  2. 关键词/意图路由(辅助方式)
    :通过简单规则快速匹配。
  3. 向量检索(大规模场景)
    :当 Skills 极多时,先用向量搜索筛选相关子集,再交给 LLM。

第六部分:Skill 与 MCP 的协同工作流(完整示例)

这个部分用一个完整的"发邮件"场景,展示知识(Skill)和行动(Tool)如何配合,以及代码层面如何实现。

6.1 场景设定

  • 一个 MCP Server,暴露了业务工具:validate_emailcompose_emailsend_email
  • 几个 Skill 文件,存放在 ./skills/ 目录下
  • 一个 LangGraph Agent,负责调度一切

6.2 准备工作:定义工具和 Skill

① MCP Server 上的业务工具(tool_server.py

from fastapi import FastAPIfrom fastapi_mcp import FastApiMCPapp = FastAPI()@app.post("/validate_email", operation_id="validate_email")async def validate_email(address: str) -> dict:    """校验收件人邮箱格式是否正确"""    if "@" in address and "." in address:        return {"valid"True"address": address}    return {"valid"False"reason""邮箱格式不正确"}@app.post("/compose_email", operation_id="compose_email")async def compose_email(to: str, subject: str, body: str) -> dict:    """生成邮件草稿并返回预览"""    draft = f"收件人: {to}\n主题: {subject}\n正文: {body}"    return {"draft": draft, "status""ready_for_review"}@app.post("/send_email", operation_id="send_email")async def send_email(to: str, subject: str, body: str) -> dict:    """实际发送邮件"""    return {"status""sent""message"f"邮件已成功发送至 {to}"}mcp = FastApiMCP(app, name="邮件工具箱", base_url="http://localhost:8000")mcp.mount()

② Skill 文件(./skills/send_email/SKILL.md

# 发送邮件标准流程1. 使用 `validate_email` 校验收件人地址格式。2. 如果格式错误,提示用户修正后重新开始。3. 使用 `compose_email` 生成邮件草稿。4. 将草稿展示给用户确认(等待用户回复"确认"或"取消")。5. 用户确认后,使用 `send_email` 发送邮件。6. 发送成功后,向用户报告结果。

③ Skill 管理工具(本地 @tool 函数)

import osfrom langchain_core.tools import toolSKILLS_DIR = "./skills"@tooldef list_skills() -> str:    """列出所有可用技能的元数据(名称 + 简短描述)"""    skills = []    for skill_name in os.listdir(SKILLS_DIR):        path = os.path.join(SKILLS_DIR, skill_name, "SKILL.md")        if os.path.isfile(path):            with open(path, "r", encoding="utf-8"as f:                first_line = f.readline().strip("# ").strip()            skills.append(f"- {skill_name}{first_line}")    return "\n".join(skills) if skills else "暂无可用技能。"@tooldef load_skill(skill_name: str) -> str:    """加载指定技能的完整 SKILL.md 内容"""    path = os.path.join(SKILLS_DIR, skill_name, "SKILL.md")    if not os.path.isfile(path):        return f"技能 '{skill_name}' 不存在。"    with open(path, "r", encoding="utf-8"as f:        return f.read()

6.3 核心:用 LangGraph 组装 Agent

将上述所有工具(MCP 业务工具 + Skill 管理工具)统一注入 Agent:

import asynciofrom langgraph.prebuilt import create_react_agentfrom langchain_mcp_adapters.client import MCPClientfrom langchain_openai import ChatOpenAIasync def main():    # ====== 第一步:加载所有工具 ======    # 1. 从 MCP Server 动态加载业务工具    mcp_client = MCPClient(server_url="http://localhost:8000/mcp")    mcp_tools = await mcp_client.load_tools()    # 2. 合并本地 Skill 管理工具    all_tools = mcp_tools + [list_skills, load_skill]    # ====== 第二步:创建 Agent(注入人格提示词) ======    system_prompt = """你是一个专业的邮件助手。你有以下能力:1. 调用 `list_skills` 查看可用的操作手册。2. 当用户的任务需要标准流程指导时,先调用 `load_skill` 获取详细步骤,再按步骤执行。3. 严格按照加载的 Skill 文件中的流程操作,不要跳过任何步骤。4. 在发送邮件前,必须先展示草稿并等待用户确认。"""    llm = ChatOpenAI(model="gpt-4o", temperature=0)    agent = create_react_agent(llm, all_tools, system_prompt=system_prompt)    # ====== 第三步:运行 ======    result = await agent.ainvoke({        "messages": [            {"role""user""content""帮我给 john@example.com 发一封邮件,主题'会议纪要',正文'明天下午三点开会'。"}        ]    })    print(result["messages"][-1].content)if __name__ == "__main__":    asyncio.run(main())

6.4 完整的执行流程

步骤
Agent 动作
工具来源
说明
1
收到用户任务
LLM 判断需要发邮件,但不确定完整流程
2
调用 list_skills()
本地 @tool
看到 send_email: 发送邮件标准流程L1 元数据
3
调用 load_skill("send_email")
本地 @tool
获取完整 SKILL.md 内容(L2 渐进式加载
4
阅读手册,按步骤1执行
需要先校验邮箱
5
调用 validate_email(...)
MCP 工具
返回 {"valid": true}
6
按步骤3执行
生成草稿
7
调用 compose_email(...)
MCP 工具
返回草稿预览
8
展示草稿,等待用户确认
用户回复"确认"
9
按步骤5执行
发送邮件
10
调用 send_email(...)
MCP 工具
返回发送成功
11
生成最终回复
“邮件已成功发送至 john@example.com!”

6.5 关键要点

  1. 工具列表注入 LLM
    :启动时通过 MCPClient.load_tools() 动态获取 MCP 工具,与本地 @tool 函数合并,统一传给 create_react_agent()
  2. 渐进式披露
    list_skills 只返回元数据(L1),LLM 决定使用后才调用 load_skill 获取完整内容(L2)。
  3. Skill 与 MCP 的分工
    : 
    • Skill (.md 文件)
      :知识层,告诉 LLM “怎么做”。
    • Skill 管理工具 (list_skills/load_skill)
      :工具层,负责"搬运知识"。
    • MCP 业务工具 (validate_email等)
      :工具层,负责"执行动作"。
  4. LLM 的角色
    :阅读 Skill 手册后,自主规划并按顺序调用 MCP 工具完成任务。

第七部分:Agent 的自进化 —— 实用简化方案

7.1 进化思路

完整自进化系统(如 Hermes)非常复杂,包含多条件触发、多层记忆、自动修复等机制。但对于一般项目,我们只需要一个最小可行自进化:通过简单的规则让 Agent 自主创建和更新 Skill,实现经验沉淀。

7.2 简化版设计

核心规则

触发条件
动作
产出
Agent 调用了 3个以上不同工具 完成任务
调用 skill_create 生成新技能
skills/xxx.md
用户纠正 Agent 的做法(说“不对/错了/应该这样”)
调用 skill_update 修改相关技能
更新对应 SKILL.md
每次任务开始前
Agent 可调用 list_skills 检查有无新技能
无额外产出

所需工具

  • skill_create
    :创建新技能文件。
  • skill_update
    :更新已有技能文件。
  • list_skills
     / load_skill:渐进式加载技能知识。

7.3 完整端到端实现

这里给出一个融合了业务工具、技能管理和自进化的完整可运行示例。Agent 执行退款任务时会自动沉淀技能。

① MCP Server (tool_server.py)

from fastapi import FastAPIfrom fastapi_mcp import FastApiMCPapp = FastAPI()@app.post("/validate_email", operation_id="validate_email")async def validate_email(address: str) -> dict:    if "@" in address and "." in address:        return {"valid"True"address": address}    return {"valid"False"reason""邮箱格式不正确"}@app.post("/compose_email", operation_id="compose_email")async def compose_email(to: str, subject: str, body: str) -> dict:    draft = f"收件人: {to}\n主题: {subject}\n正文: {body}"    return {"draft": draft, "status""ready_for_review"}@app.post("/send_email", operation_id="send_email")async def send_email(to: str, subject: str, body: str) -> dict:    return {"status""sent""message"f"邮件已发送至 {to}"}@app.get("/query_order", operation_id="query_order")async def query_order(order_id: str) -> dict:    return {"order_id": order_id, "status""已完成""refundable"True}@app.post("/refund_create", operation_id="refund_create")async def refund_create(order_id: str) -> dict:    return {"refund_id""R123""status""退款已发起"}mcp = FastApiMCP(app, name="业务工具箱", base_url="http://localhost:8000")mcp.mount()

② 本地 Skill 管理工具 (skill_tools.py)

import osfrom langchain_core.tools import toolSKILLS_DIR = "./skills"os.makedirs(SKILLS_DIR, exist_ok=True)@tooldef list_skills() -> str:    skills = []    for skill_name in os.listdir(SKILLS_DIR):        path = os.path.join(SKILLS_DIR, skill_name, "SKILL.md")        if os.path.isfile(path):            with open(path, "r", encoding="utf-8"as f:                first_line = f.readline().strip("# ").strip()            skills.append(f"- {skill_name}{first_line}")    return "\n".join(skills) if skills else "暂无可用技能。"@tooldef load_skill(skill_name: str) -> str:    path = os.path.join(SKILLS_DIR, skill_name, "SKILL.md")    if not os.path.isfile(path):        return f"技能 '{skill_name}' 不存在。"    with open(path, "r", encoding="utf-8"as f:        return f.read()@tooldef skill_create(name: str, description: str, content: str) -> str:    path = os.path.join(SKILLS_DIR, name, "SKILL.md")    os.makedirs(os.path.dirname(path), exist_ok=True)    with open(path, "w", encoding="utf-8"as f:        f.write(f"# {description}\n\n{content}")    return f"技能 '{name}' 已创建。"@tooldef skill_update(skill_name: str, new_content: str) -> str:    path = os.path.join(SKILLS_DIR, skill_name, "SKILL.md")    if not os.path.isfile(path):        return f"技能 '{skill_name}' 不存在,请先用 skill_create 创建。"    with open(path, "w", encoding="utf-8"as f:        f.write(new_content)    return f"技能 '{skill_name}' 已更新。"

③ 带自进化的 Agent 主程序 (agent.py)

import asynciofrom langgraph.prebuilt import create_react_agentfrom langchain_mcp_adapters.client import MCPClientfrom langchain_openai import ChatOpenAIfrom skill_tools import list_skills, load_skill, skill_create, skill_updateasync def main():    # 加载工具    mcp_client = MCPClient(server_url="http://localhost:8000/mcp")    mcp_tools = await mcp_client.load_tools()    all_tools = mcp_tools + [list_skills, load_skill, skill_create, skill_update]    # 系统提示词(含自进化指令)    system_prompt = """你是一个智能助手,拥有自我进化能力。## 核心行为准则1. 当需要执行标准化流程时,先调用 `list_skills` 查看是否有现成技能。2. 若有相关技能,调用 `load_skill` 获取详细步骤并严格遵循。3. 若无现成技能,使用通用推理完成任务。## 自我进化规则(重要!)1. **创建新技能**:完成一个任务后,若满足以下任一条件,请调用 `skill_create` 沉淀经验:   - 任务中调用了 **3个以上不同的工具**   - 这是一个你之前没做过的新流程   - 用户要求记住这个做法2. **更新现有技能**:若用户明确指出你的做法有误或不够好,请调用 `skill_update` 修正对应技能。3. 技能名称用英文小写+下划线,内容简洁可操作,Markdown 格式。"""    llm = ChatOpenAI(model="gpt-4o", temperature=0)    agent = create_react_agent(llm, all_tools, system_prompt=system_prompt)    # 运行:处理退款(新任务,将触发自进化)    result = await agent.ainvoke({        "messages": [            {"role""user""content""请帮我把订单 #1234 退款,并邮件通知客户 john@example.com。"}        ]    })    print("Agent 回复:", result["messages"][-1].content)if __name__ == "__main__":    asyncio.run(main())

7.4 执行流程与进化演示

步骤
Agent 动作
工具来源
说明
1
收到用户退款请求
任务复杂,涉及查单、退款、发邮件
2
调用 list_skills()
本地
检查是否有退款相关技能(返回空)
3
发现无现成技能,开始通用推理
自行决定流程
4
调用 query_order("1234")
MCP
确认订单可退款
5
调用 refund_create("1234")
MCP
发起退款
6
调用 validate_email("john@example.com")
MCP
校验邮箱
7
调用 send_email(...)
MCP
发送通知邮件
8
触发进化
(调用了4个工具≥3)
Agent 决定沉淀技能
9
调用 skill_create("handle_refund", "退款处理标准流程", "1. 用 query_order 查订单\n2. 若可退款,用 refund_create 发起退款\n3. 用 validate_email 校验邮箱\n4. 用 send_email 通知客户")
本地
技能文件写入 ./skills/handle_refund/SKILL.md
10
生成最终回复
“退款已处理完毕,邮件已通知客户。”

第二次使用(进化已生效)

用户: 帮我把订单 #5678 也退款,通知 alice@example.com。Agent: 调用 list_skills → 发现 handle_refund 技能 → 调用 load_skill → 按步骤自动执行所有操作。

7.5 与完整方案的对比

完整 Hermes 方案
我们的简化版
五层记忆体系
只用 .md 文件 + list_skills 发现
多条件触发评估
两个简单规则:工具数≥3 或用户纠正
自动精准修复
skill_update
 全量替换,LLM 自主决定修改内容
后台持续自循环
每次任务后即时判断,不跑后台服务

这个方案零额外框架、零额外服务,只靠 Prompt 规则和已有的 skill_create/skill_update 就能跑起来,适合日常项目使用。


基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-05-24 17:20:03 HTTP/1.1 GET : https://www.yeyulingfeng.com/a/662862.html
  2. 运行时间 : 0.119215s [ 吞吐率:8.39req/s ] 内存消耗:4,814.55kb 文件加载:145
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=9efbb43befde2dbcd714bc606ca8b3f4
  1. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/autoload_static.php ( 6.05 KB )
  7. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/ralouphie/getallheaders/src/getallheaders.php ( 1.60 KB )
  10. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  11. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  12. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  13. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  14. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  15. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  16. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  17. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  18. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  19. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/guzzlehttp/guzzle/src/functions_include.php ( 0.16 KB )
  21. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/guzzlehttp/guzzle/src/functions.php ( 5.54 KB )
  22. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  23. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  24. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  25. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/provider.php ( 0.19 KB )
  26. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  27. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  28. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  29. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/common.php ( 0.03 KB )
  30. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  32. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/alipay.php ( 3.59 KB )
  33. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  34. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/app.php ( 0.95 KB )
  35. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/cache.php ( 0.78 KB )
  36. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/console.php ( 0.23 KB )
  37. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/cookie.php ( 0.56 KB )
  38. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/database.php ( 2.48 KB )
  39. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/filesystem.php ( 0.61 KB )
  40. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/lang.php ( 0.91 KB )
  41. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/log.php ( 1.35 KB )
  42. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/middleware.php ( 0.19 KB )
  43. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/route.php ( 1.89 KB )
  44. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/session.php ( 0.57 KB )
  45. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/trace.php ( 0.34 KB )
  46. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/view.php ( 0.82 KB )
  47. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/event.php ( 0.25 KB )
  48. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  49. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/service.php ( 0.13 KB )
  50. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/AppService.php ( 0.26 KB )
  51. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  52. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  53. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  54. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  55. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  56. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/services.php ( 0.14 KB )
  57. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  58. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  59. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  60. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  61. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  62. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  63. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  64. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  65. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  66. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  67. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  68. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  69. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  70. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  71. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  72. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  73. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  74. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  75. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  76. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  77. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  78. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  79. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  80. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  81. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  82. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  83. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  84. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  85. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  86. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  87. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/Request.php ( 0.09 KB )
  88. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  89. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/middleware.php ( 0.25 KB )
  90. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  91. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  92. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  93. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  94. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  95. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  96. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  97. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  98. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  99. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  100. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  101. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  102. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  103. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/route/app.php ( 3.94 KB )
  104. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  105. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  106. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/controller/Index.php ( 9.87 KB )
  108. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/BaseController.php ( 2.05 KB )
  109. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  110. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  111. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  112. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  113. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  114. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  115. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  116. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  117. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  118. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  119. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  120. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  121. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  122. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  123. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  124. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  125. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  126. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  127. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  128. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  129. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  130. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  131. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  132. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  133. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  134. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  135. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/controller/Es.php ( 3.30 KB )
  136. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  137. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  138. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  139. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  140. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  141. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  142. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  143. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  144. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/runtime/temp/c935550e3e8a3a4c27dd94e439343fdf.php ( 31.50 KB )
  145. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000607s ] mysql:host=127.0.0.1;port=3306;dbname=wenku;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000654s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.002252s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000282s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000486s ]
  6. SELECT * FROM `set` [ RunTime:0.000224s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000549s ]
  8. SELECT * FROM `article` WHERE `id` = 662862 LIMIT 1 [ RunTime:0.005466s ]
  9. UPDATE `article` SET `lasttime` = 1779614403 WHERE `id` = 662862 [ RunTime:0.004664s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 64 LIMIT 1 [ RunTime:0.000261s ]
  11. SELECT * FROM `article` WHERE `id` < 662862 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000454s ]
  12. SELECT * FROM `article` WHERE `id` > 662862 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.001175s ]
  13. SELECT * FROM `article` WHERE `id` < 662862 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.000627s ]
  14. SELECT * FROM `article` WHERE `id` < 662862 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.001175s ]
  15. SELECT * FROM `article` WHERE `id` < 662862 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.003120s ]
0.124941s