当前位置:首页>python>手把手教你用 Python 从零写一个 AI Agent(无框架,DeepSeek 版)

手把手教你用 Python 从零写一个 AI Agent(无框架,DeepSeek 版)

  • 2026-02-06 15:37:45
手把手教你用 Python 从零写一个 AI Agent(无框架,DeepSeek 版)

在这篇文章中,不使用 LangChain 等现成框架,回归本质,用 Python 从零构建一个真正可落地的最小化 Agent 循环。我将实现以下核心功能: 

     工具调用(安全且可预测)

     记忆机制(短期对话 + 长期笔记)

     规划与重规划(简单实用,不搞花架子)

     硬停止条件(防止 Agent 失控)

     完整的追踪日志(方便调试和优化)

1、“AI Agent” 的本质逻辑 

要从零构建 Agent,你只需要理解这一个核心公式: 

Agent 是一个循环:

规划 → 行动(使用工具) → 观察 → 记忆 → 重新规划 → 停止 

这就完了。 

普通的聊天机器人是一次性问答;而 Agent 的核心能力在于自主决策下一步行动,并能通过工具持续交互,直到任务完成。 

这里有一个行业内默认的“潜规则”: 

    优秀的 Agent 往往不追求“高智商”,而是追求“高可控性”。 

因此,接下来的代码将重点聚焦于控制:结构化输出、工具安全沙箱、记忆压缩以及强制停止条件。 

2、Agent 的架构设计 

我将实现四大模块: 

1) 工具系统 

本质上就是封装好的 Python 函数,但必须包含以下元数据: 

     名称:调用时的标识。

     描述:告诉 LLM 这个工具是干嘛的。

     输入模式:定义参数的 JSON Schema。

2) 记忆系统 

双层设计: 

     短期记忆:保存最近的对话上下文和工具执行结果(类似 RAM)。

     长期记忆:将关键信息持久化到磁盘,需要时通过关键词检索(类似硬盘,这里暂不引入复杂的向量库,保持轻量)。

3) 规划系统 

     高层规划:由 3-6 个关键点组成的任务大纲。

     下一步行动:当前这一步具体要做什么(调用工具或直接回答)。

4) 停止条件 

这是区分“玩具 Demo”和“生产级 Agent”的关键: 

     硬限制:最大步数、最大工具调用次数、最大超时时间。

     软限制:检测到重复动作、连续两步无进展时自动停止。

3、完整工作代码 

这是一个纯 Python 实现的最小化 AI Agent(不依赖 LangChain)。 

环境要求: 

     Python 3.10+

环境变量配置: 

     DEEPSEEK_API (必须)

     DEEPSEEK_URL (可选,默认: https://api.deepseek.com )

     DEEPSEEK_MODEL (可选,默认: deepseek-chat)

流程图:

"""------------------------------------------------------------基于原生 Python 实现的最小化 AI Agent 循环 (无 LangChain)。- 工具系统:注册中心 + 安全执行- 记忆系统:短期上下文 + 基于文件的长期笔记- 规划系统:简易计划表 + 下一步行动- 安全护栏:最大步数、工具调用限制、循环检测- 调试支持:每一步的详细追踪日志"""from __future__ import annotationsimport jsonimport osimport timeimport refrom dataclasses import dataclass, fieldfrom typing import AnyCallableDictListOptionalTupleimport requests# -----------------------------# 工具函数# -----------------------------from dotenv import load_dotenvdef now_ms() -> int:    """获取当前时间戳(毫秒)"""    return int(time.time() * 1000)def clamp_text(text: str, max_chars: int = 1800) -> str:    """截断过长的文本,防止 Token 溢出"""    text = text.strip()    if len(text) <= max_chars:        return text    return text[:max_chars] + " ...[已截断]"def safe_json_extract(text: str) -> Optional[Dict[strAny]]:    """    安全地从模型回复中提取 JSON 对象。    模型必须输出单个 JSON 对象,此函数尝试提取第一个 {...} 块。    """    text = text.strip()    # 快速路径:纯 JSON    if text.startswith("{"and text.endswith("}"):        try:            return json.loads(text)        except Exception:            pass    # 正则提取第一个 {...} 代码块    match = re.search(r"\{.*\}", text, flags=re.DOTALL)    if not match:        return None    blob = match.group(0)    try:        return json.loads(blob)    except Exception:        return Nonedef simple_similarity(a: str, b: str) -> float:    """    微小的循环检测启发式算法:基于 token 重叠率。    足以检测“反复执行相同动作”的死循环情况。    """    sa = set(a.lower().split())    sb = set(b.lower().split())    if not sa or not sb:        return 0.0    return len(sa & sb) / max(1len(sa | sb))# -----------------------------# 工具系统# -----------------------------@dataclassclass Tool:    name: str    description: str    schema: Dict[strAny]    fn: Callable[[Dict[strAny]], Any]    safe: bool = True  # 标记是否为危险工具(如写文件)class ToolRegistry:    def __init__(self) -> None:        self._tools: Dict[str, Tool] = {}    def register(self, tool: Tool) -> None:        if tool.name in self._tools:            raise ValueError(f"工具已注册: {tool.name}")        self._tools[tool.name] = tool    def get(self, name: str) -> Optional[Tool]:        return self._tools.get(name)    def as_prompt_block(self) -> str:        """        将工具列表转换为紧凑、易读的 Prompt 文本块。        """        lines = ["可用工具列表:"]        for t in self._tools.values():            safe_tag = "安全" if t.safe else "受限"            lines.append(f"- {t.name} ({safe_tag}): {t.description}")            lines.append(f"  参数定义: {json.dumps(t.schema, ensure_ascii=False)}")        return "\n".join(lines)# -----------------------------# 记忆系统# -----------------------------@dataclassclass MemoryNote:    ts_ms: int    text: str    tags: List[str] = field(default_factory=list)class LongTermMemory:    """    简单的长期记忆:    - 将紧凑的笔记存储在 JSONL 文件中    - 基于关键词重叠进行检索(简单、快速、无需向量库)    """    def __init__(self, path: str = "agent_memory.jsonl") -> None:        self.path = path        if not os.path.exists(self.path):            with open(self.path, "w", encoding="utf-8"as f:                f.write("")    def add(self, text: str, tags: Optional[List[str]] = None) -> None:        note = MemoryNote(ts_ms=now_ms(), text=text.strip(), tags=tags or [])        with open(self.path, "a", encoding="utf-8"as f:            f.write(json.dumps(note.__dict__, ensure_ascii=False) + "\n")    def search(self, query: str, k: int = 5) -> List[MemoryNote]:        query_tokens = set(query.lower().split())        scored: List[Tuple[float, MemoryNote]] = []        with open(self.path, "r", encoding="utf-8"as f:            for line in f:                line = line.strip()                if not line:                    continue                try:                    obj = json.loads(line)                    note = MemoryNote(**obj)                    tokens = set(note.text.lower().split())                    score = len(tokens & query_tokens)                    if score > 0:                        scored.append((float(score), note))                except Exception:                    continue        scored.sort(key=lambda x: x[0], reverse=True)        return [n for _, n in scored[:k]]class ShortTermMemory:    """    保存最近的 N 条消息(已压缩)。    """    def __init__(self, max_items: int = 18) -> None:        self.max_items = max_items        self.items: List[Dict[strstr]] = []    def add(self, role: str, content: str) -> None:        self.items.append({"role": role, "content": content})        if len(self.items) > self.max_items:            self.items = self.items[-self.max_items:]# -----------------------------# LLM 客户端 (DeepSeek)# -----------------------------load_dotenv()class LLMClient:    def __init__(self) -> None:        # 适配国内环境,优先读取 DeepSeek 配置        self.api_key = os.environ['DEEPSEEK_API'].strip()        if not self.api_key:            raise RuntimeError("缺少 API Key,请设置环境变量 DEEPSEEK_API_KEY")        # DeepSeek 兼容 OpenAI 接口格式        self.base_url = os.environ['DEEPSEEK_URL'].strip()        if not self.base_url.endswith("/v1"):            # 兼容用户可能输入不带 v1 的情况            self.base_url = self.base_url.rstrip("/") + "/v1"        self.model = os.environ['DEEPSEEK_MODEL'].strip()    def chat(self, messages: List[Dict[strstr]], temperature: float = 0.2) -> str:        url = f"{self.base_url}/chat/completions"        headers = {"Authorization"f"Bearer {self.api_key}"}        payload = {            "model"self.model,            "temperature": temperature,            "messages": messages,        }        try:            r = requests.post(url, headers=headers, json=payload, timeout=60)            r.raise_for_status()            data = r.json()            return data["choices"][0]["message"]["content"]        except Exception as e:            return f"LLM 调用错误: {str(e)}"# -----------------------------# Agent 核心逻辑# -----------------------------@dataclassclass AgentConfig:    max_steps: int = 10  # 最大思考步数    max_tool_calls: int = 6  # 最大工具调用次数    max_seconds: int = 35  # 最大运行时间(秒)    allow_restricted_tools: bool = False  # 是否允许使用危险工具@dataclassclass AgentState:    step: int = 0    tool_calls: int = 0    started_ms: int = field(default_factory=now_ms)    high_level_plan: List[str] = field(default_factory=list)    last_actions: List[str] = field(default_factory=list)  # 用于检测循环    trace: List[Dict[strAny]] = field(default_factory=list)  # 调试追踪class ScratchAgent:    """    最小化 Agent 实现:    - 请求模型生成计划 + 下一步行动    - 按需执行工具    - 存储记忆笔记    - 安全停止    """    def __init__(self, llm: LLMClient, tools: ToolRegistry, ltm: LongTermMemory, cfg: AgentConfig) -> None:        self.llm = llm        self.tools = tools        self.ltm = ltm        self.cfg = cfg        self.stm = ShortTermMemory(max_items=18)    def _time_left(self, state: AgentState) -> int:        elapsed = now_ms() - state.started_ms        return max(0self.cfg.max_seconds * 1000 - elapsed)    def _should_stop(self, state: AgentState) -> Optional[str]:        """检查是否满足停止条件"""        if state.step >= self.cfg.max_steps:            return "已达到最大步数限制"        if state.tool_calls >= self.cfg.max_tool_calls:            return "已达到最大工具调用次数"        if self._time_left(state) <= 0:            return "已达到最大运行时长"        # 循环检测:如果连续执行非常相似的动作        if len(state.last_actions) >= 3:            a, b, c = state.last_actions[-3:]            if simple_similarity(a, b) > 0.85 and simple_similarity(b, c) > 0.85:                return "检测到重复动作循环"        return None    def _compact_memory_summary(self) -> str:        """        将短期记忆压缩为 Agent 可以携带的紧凑摘要。        """        # 仅保留最后 8 条,并压缩换行符        tail = self.stm.items[-8:]        lines = []        for it in tail:            role = it["role"]            content = clamp_text(it["content"], 260).replace("\n"" ")            lines.append(f"{role}{content}")        return "\n".join(lines)    def _build_system_prompt(self, user_goal: str) -> str:        """        最核心的部分:严格的输出格式 + 清晰的行为规范。        """        return f"""你是一个严谨的 AI Agent。你的任务是安全、高效地完成用户的目标。用户目标:{user_goal}规则:- 你必须且只能回复一个 JSON 对象,不要包含任何其他废话。- 每一步只能选择一个动作。- 如果信息充足,直接给出最终答案。- 保持计划简短扼要。- 避免死循环。如果卡住了,说明缺失了什么信息,然后尝试结束任务。输出 JSON 格式定义:{{  "type": "plan" | "tool_call" | "final",  "plan": ["..."] (当 type="plan" 时必填, 高层计划列表),  "next": "...一句话描述下一步..." (当 type="plan" 时必填),  "tool": "工具名称" (当 type="tool_call" 时必填),  "args": {{...}} (当 type="tool_call" 时必填, 工具参数),  "answer": "...最终答案..." (当 type="final" 时必填),  "memory_note": "...需要长期存储的简短笔记..." (可选)}}{self.tools.as_prompt_block()}""".strip()    def _model_step(self, user_goal: str, state: AgentState) -> Dict[strAny]:        # 检索长期记忆        ltm_hits = self.ltm.search(user_goal, k=4)        ltm_block = "\n".join([f"- {clamp_text(n.text, 240)}" for n in ltm_hits]) or "- (无历史记忆)"        system = self._build_system_prompt(user_goal)        context = f"""短期记忆 (摘要):{self._compact_memory_summary()}长期记忆 (相关历史):{ltm_block}当前计划:{state.high_level_plan if state.high_level_plan else"(尚未制定)"}当前步骤: {state.step}已用工具调用: {state.tool_calls}剩余时间: {self._time_left(state) / 1000:.1f}s""".strip()        messages = [            {"role""system""content": system},            {"role""user""content": context},        ]        raw = self.llm.chat(messages, temperature=0.2)        obj = safe_json_extract(raw)        if not obj:            # 容错:如果解析失败,强制结束以防乱跑            return {"type""final""answer": clamp_text(raw, 900)}        return obj    def _run_tool(self, name: str, args: Dict[strAny]) -> Dict[strAny]:        tool = self.tools.get(name)        if not tool:            return {"ok"False"error"f"未知工具: {name}""data"None"latency_ms"0}        if (not tool.safe) and (not self.cfg.allow_restricted_tools):            return {"ok"False"error"f"工具受限: {name}""data"None"latency_ms"0}        t0 = now_ms()        try:            out = tool.fn(args)            return {"ok"True"error"None"data": out, "latency_ms": now_ms() - t0}        except Exception as e:            return {"ok"False"error"str(e), "data"None"latency_ms": now_ms() - t0}    def run(self, user_goal: str) -> str:        state = AgentState()        self.stm.add("user", user_goal)        while True:            stop_reason = self._should_stop(state)            if stop_reason:                final = f"安全停止: {stop_reason}。\n\n建议下一步:澄清缺失信息或缩小任务范围。"                self.stm.add("assistant", final)                return final            state.step += 1            decision = self._model_step(user_goal, state)            dtype = decision.get("type""").strip()            trace_item: Dict[strAny] = {                "step": state.step,                "decision": decision,                "tool_result"None,            }            # 存储记忆笔记 (如果模型提供了)            mem_note = (decision.get("memory_note"or "").strip()            if mem_note:                self.ltm.add(mem_note, tags=["agent_note"])            if dtype == "plan":                plan = decision.get("plan"or []                if isinstance(plan, listand plan:                    state.high_level_plan = [str(x)[:140for x in plan][:6]                nxt = str(decision.get("next"or "").strip()                state.last_actions.append("plan:" + nxt)                self.stm.add("assistant"f"PLAN: {state.high_level_plan}\nNEXT: {nxt}")                state.trace.append(trace_item)                continue            if dtype == "tool_call":                tool_name = str(decision.get("tool"or "").strip()                args = decision.get("args"or {}                if not isinstance(args, dict):                    args = {}                state.tool_calls += 1                action_sig = f"tool:{tool_name} args:{json.dumps(args, sort_keys=True)}"                state.last_actions.append(action_sig)                result = self._run_tool(tool_name, args)                trace_item["tool_result"] = result                state.trace.append(trace_item)                obs = {                    "tool": tool_name,                    "ok": result["ok"],                    "error": result["error"],                    "data": clamp_text(json.dumps(result["data"], ensure_ascii=False), 1200if result["ok"else None,                    "latency_ms": result["latency_ms"],                }                self.stm.add("assistant"f"TOOL_OBSERVATION: {json.dumps(obs, ensure_ascii=False)}")                continue            # 最终答案            answer = str(decision.get("answer"or "").strip()            if not answer:                answer = "任务结束。"            self.stm.add("assistant", answer)            return answer# -----------------------------# 内置工具 (安全且实用)# -----------------------------def tool_calc(args: Dict[strAny]) -> Any:    """安全的计算器"""    expr = str(args.get("expression""")).strip()    if not expr:        raise ValueError("缺少表达式")    # 仅允许数字和基本运算符    if not re.fullmatch(r"[0-9\.\+\-\*\/\(\)\s]+", expr):        raise ValueError("表达式包含非法字符")    return eval(expr, {"__builtins__": {}}, {})def tool_summarize(args: Dict[strAny]) -> Any:    """简单的文本摘要工具"""    text = str(args.get("text""")).strip()    max_lines = int(args.get("max_lines"6))    text = clamp_text(text, 3000)    lines = [ln.strip() for ln in text.splitlines() if ln.strip()]    # 启发式摘要:取前几行 + 关键点(这里简单取前N行)    out = []    for ln in lines[:max_lines]:        out.append(ln[:180])    return outdef tool_read_file(args: Dict[strAny]) -> Any:    """读取本地文本文件"""    path = str(args.get("path""")).strip()    if not path:        raise ValueError("缺少路径参数")    # 禁止父目录遍历    if ".." in path.replace("\\""/"):        raise ValueError("禁止访问父目录")    with open(path, "r", encoding="utf-8"as f:        return clamp_text(f.read(), 6000)def build_tools() -> ToolRegistry:    reg = ToolRegistry()    reg.register(Tool(        name="calc",        description="安全地计算数学表达式 (数字 + - * / 括号)",        schema={"type""object""properties": {"expression": {"type""string"}}, "required": ["expression"]},        fn=tool_calc,        safe=True,    ))    reg.register(Tool(        name="summarize",        description="从长文本中生成简短的要点摘要",        schema={"type""object""properties": {"text": {"type""string"}, "max_lines": {"type""integer"}},                "required": ["text"]},        fn=tool_summarize,        safe=True,    ))    reg.register(Tool(        name="read_file",        description="读取本地文本文件 (禁止父目录遍历)",        schema={"type""object""properties": {"path": {"type""string"}}, "required": ["path"]},        fn=tool_read_file,        safe=False,  # 文件读取默认视为受限操作    ))    return reg# -----------------------------# 演示 / Demo# -----------------------------if __name__ == "__main__":    # 初始化 LLM (DeepSeek)    llm = LLMClient()    # 构建工具集    tools = build_tools()    # 初始化记忆    ltm = LongTermMemory(path="agent_memory.jsonl")    # Agent 配置    cfg = AgentConfig(        max_steps=10,        max_tool_calls=6,        max_seconds=35,        allow_restricted_tools=False,    )    # 实例化 Agent    agent = ScratchAgent(llm=llm, tools=tools, ltm=ltm, cfg=cfg)    # 执行任务    goal = (        "制定一个简短的旅游计划,目的地是北京,计划包括整个费用,路线,酒店,吃饭,风景名胜古迹等。"    )    print("-" * 50)    print("Agent 开始运行...")    print("-" * 50)    result = agent.run(goal)    print("-" * 50)    print("最终结果:")    print(result)

问题:

# 执行任务goal = (    "制定一个简短的旅游计划,目的地是北京,计划包括整个费用,路线,酒店,吃饭,风景名胜古迹等。")

回答:

--------------------------------------------------Agent 开始运行...----------------------------------------------------------------------------------------------------最终结果:**北京3天2晚经典游计划****总费用估算:约 1800-2500 元/人** (经济型,不含往返大交通)**路线与景点:**- **第1天:** 天安门广场 -> 故宫 -> 景山公园 (俯瞰故宫全景) -> 王府井步行街 (晚餐)- **第2天:** 八达岭长城 (上午) -> 鸟巢、水立方 (外观,下午) -> 什刹海/后海 (晚餐与夜景)- **第3天:** 颐和园 (上午) -> 圆明园 (下午部分区域) -> 返程**酒店:** 选择地铁沿线经济型酒店或连锁酒店 (如如家、汉庭),约 300-400 元/晚。建议住在东城区、西城区或海淀区地铁站附近。**吃饭:**- 每日餐饮预算约 100-150 元/人,可品尝北京烤鸭、炸酱面、卤煮、涮羊肉等。- 推荐地点:王府井小吃街、前门大街、牛街、以及各大商圈。**费用明细 (人均估算):**- 住宿:2晚 * 350元 = 700元- 餐饮:3天 * 120元 = 360元- 门票 (故宫60,长城40,颐和园30,景山2,圆明园10):约 142元- 市内交通 (地铁、公交):约 50元- 其他 (零食、纪念品):约 100元**总计:约 1352元 (基础) + 弹性 = 1800-2500元****提示:** 提前在线预订门票,使用地铁APP,避开早晚高峰。Process finished with exit code 0

4、为什么这个“从零实现”的 Agent 真的有效?

以下是该设计的关键优势:

1) 强制结构化 JSON 输出

当输出不可控时,Agent 就会崩溃。在这个实现中,模型被严格要求进行三选一:

  • plan
    (制定计划)
  • tool_call
    (调用工具)
  • final
    (完成任务)

这看似简单的约束,消除了 80% 的 Agent 幻觉和逻辑混乱。

2) 将工具输出视为“观察结果”

Agent 不会凭空“猜测”世界状态。它必须执行一个动作,获得真实的反馈,然后基于这些反馈更新记忆。这种闭环机制保证了逻辑的严密性。

3) 具备真正的“硬停止”条件

大多数入门教程会忽略这一点,但这恰恰是生产环境的关键。 如果你的 Agent 永远不知道何时停下来,那它就不是一个助手,而是一个失控的后台进程(甚至是一笔巨额的 API 账单)。通过限制步数、时间和检测重复动作,我确保了系统的底线安全。

4) 紧凑的记忆设计

我主动修剪了短期记忆,并将长期记忆设计为基于文件的快照存储。这有效防止了上下文窗口的无限膨胀——这是导致 Agent 性能下降和响应延迟增加的隐形杀手。

最新文章

随机文章

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