乐于分享
好东西不私藏

AI Agent 系列(十九):Agent 微调与训练——何时微调,SFT vs RLHF 实战指南

AI Agent 系列(十九):Agent 微调与训练——何时微调,SFT vs RLHF 实战指南

上期回顾:长上下文管理的四种策略(滑动窗口、摘要压缩、重要性加权、层级摘要)全部讲透,给出了成本对比和选型指南。这一篇进入微调与训练——当 Prompt 工程走到极限,下一步该怎么做。


一、先问自己:真的需要微调吗?

微调(Fine-tuning)是一个高成本、高收益但也高风险的决策。在花几周时间、几千美元数据标注费用、若干 GPU 小时之前,先问自己三个问题:

``` 问题1:Prompt 工程做到极限了吗?

还没做到的话,先把这些做完: ✅ 详细的系统提示词(五层结构,第八篇) ✅ Few-Shot 示例(3-10个高质量示例) ✅ CoT / ToT 推理增强(第九篇) ✅ 结构化输出约束(第十篇) ✅ 换更强的底座模型(Sonnet → Opus)

只有以上全部做完还不满意,才考虑微调。

问题2:微调能解决的问题是什么?

微调适合解决: ✅ 特定格式的输出需求(公司内部报告格式) ✅ 领域专有术语和知识(法律、医疗、金融) ✅ 特定风格和语调(品牌声音) ✅ 降低延迟(小模型微调后媲美大模型) ✅ 降低成本(用微调的小模型替代昂贵的大模型)

微调解决不了的问题: ❌ 知识截止(要用 RAG,不是微调) ❌ 实时数据(要用工具调用) ❌ 推理能力根本性提升(要换更大的基础模型) ❌ 幻觉问题(微调可能反而让幻觉更顽固)

问题3:你有足够好的训练数据吗?

没有好数据,微调只会让模型"更稳定地犯错"。 通常需要: - SFT:500-5000 条高质量标注样本 - RLHF:10000+ 条人工偏好对比数据 ```


二、微调的三种方式

``` Fine-tuning 技术谱系:

全量微调(Full Fine-tuning) └── 更新所有参数 └── 效果最好,但成本极高 └── 适合:有大量 GPU 资源的大公司

参数高效微调(PEFT) └── LoRA / QLoRA:只训练低秩适配矩阵 └── 效果接近全量,成本低 10-100 倍 └── 适合:中小团队,单 GPU 可运行 └── ✅ 当前最主流的选择

API 微调(Fine-tuning API) └── OpenAI、Anthropic 等提供的托管微调 └── 无需 GPU,按用量付费 └── 最简单,但可控性最低 └── ✅ 入门首选 ```


三、数据准备:微调成败的关键

3.1 数据格式(以 OpenAI 格式为通用标准)

```python

data/prepare.py

import json from dataclasses import dataclass from typing import Optional from pathlib import Path

@dataclass class TrainingExample: """微调训练样本""" system: str # 系统提示词 user: str # 用户输入 assistant: str # 期望的 Agent 输出 quality_score: float = 1.0 # 数据质量评分(0-1) source: str = "human" # human / synthetic / distilled

def to_openai_format(self) -> dict:
    """转换为 OpenAI Fine-tuning 格式"""
    return {
        "messages": [
            {"role": "system", "content": self.system},
            {"role": "user", "content": self.user},
            {"role": "assistant", "content": self.assistant}
        ]
    }

def to_alpaca_format(self) -> dict:
    """转换为 Alpaca 格式(Llama 微调常用)"""
    return {
        "instruction": self.system + "\n\n" + self.user,
        "input": "",
        "output": self.assistant
    }

class DatasetBuilder: """训练数据集构建器"""

def __init__(self):
    self.examples: list[TrainingExample] = []

def add(self, example: TrainingExample):
    if example.quality_score >= 0.8:  # 只加入高质量样本
        self.examples.append(example)

def add_from_logs(self, conversation_logs: list[dict], min_rating: float = 4.0):
    """
    从生产日志中提取高质量对话作为训练数据
    (这是获取真实训练数据的最佳来源)
    """
    for log in conversation_logs:
        if log.get("user_rating", 0) >= min_rating:
            example = TrainingExample(
                system=log.get("system_prompt", ""),
                user=log["user_input"],
                assistant=log["agent_output"],
                quality_score=log["user_rating"] / 5.0,
                source="production_log"
            )
            self.add(example)

def generate_synthetic(self, n: int = 100, domain: str = "general") -> list[TrainingExample]:
    """
    使用强模型生成合成训练数据
    (当真实数据不足时的补充方案)
    """
    from anthropic import Anthropic
    client = Anthropic()

    generated = []
    batch_prompts = {
        "general": "生成多样化的用户问题和高质量回答",
        "coding": "生成 Python 编程相关的问题和详细解答",
        "analysis": "生成数据分析请求和专业分析报告",
    }

    for i in range(n // 10):  # 每次生成 10 条
        response = client.messages.create(
            model="claude-sonnet-4-20250514",  # 用强模型生成
            max_tokens=3000,
            messages=[{
                "role": "user",
                "content": f"""为 AI Agent 微调生成 10 个高质量的训练样本。

领域:{domain} 要求: 1. 问题多样化(不同难度、不同类型) 2. 回答高质量(准确、完整、格式规范) 3. 包含工具调用场景(搜索、计算、代码执行)

以 JSON 数组格式输出,每条包含: {{"user": "用户输入", "assistant": "期望的 Agent 回答"}}""" }] )

        text = response.content[0].text
        import re
        match = re.search(r'\[.*\]', text, re.DOTALL)
        if match:
            items = json.loads(match.group())
            for item in items:
                generated.append(TrainingExample(
                    system=f"你是一个专业的 {domain} AI 助手。",
                    user=item.get("user", ""),
                    assistant=item.get("assistant", ""),
                    quality_score=0.85,
                    source="synthetic"
                ))

    print(f"✅ 生成了 {len(generated)} 条合成训练数据")
    return generated

def validate_quality(self) -> dict:
    """验证数据集质量"""
    if not self.examples:
        return {"status": "empty"}

    # 基础统计
    avg_user_len = sum(len(e.user) for e in self.examples) / len(self.examples)
    avg_assistant_len = sum(len(e.assistant) for e in self.examples) / len(self.examples)

    # 检查重复
    user_inputs = [e.user for e in self.examples]
    unique_ratio = len(set(user_inputs)) / len(user_inputs)

    # 检查长度分布
    short_examples = sum(1 for e in self.examples if len(e.assistant) < 50)

    return {
        "total_examples": len(self.examples),
        "avg_user_length": int(avg_user_len),
        "avg_assistant_length": int(avg_assistant_len),
        "unique_ratio": round(unique_ratio, 2),
        "short_examples_count": short_examples,
        "quality_issues": [
            f"⚠️ {short_examples} 条回答过短(<50字符)" if short_examples > 0 else None,
            f"⚠️ 唯一性只有 {unique_ratio:.0%},可能有重复" if unique_ratio < 0.9 else None,
        ]
    }

def split_and_save(self, output_dir: str, train_ratio: float = 0.9):
    """切分训练集和验证集并保存"""
    import random
    random.shuffle(self.examples)

    split_idx = int(len(self.examples) * train_ratio)
    train_set = self.examples[:split_idx]
    val_set = self.examples[split_idx:]

    output_path = Path(output_dir)
    output_path.mkdir(exist_ok=True)

    # 保存为 JSONL 格式(Fine-tuning API 要求)
    for name, dataset in [("train", train_set), ("validation", val_set)]:
        path = output_path / f"{name}.jsonl"
        with open(path, "w", encoding="utf-8") as f:
            for example in dataset:
                f.write(json.dumps(example.to_openai_format(), ensure_ascii=False) + "\n")

    print(f"✅ 数据集已保存:{len(train_set)} 训练 / {len(val_set)} 验证")
    return str(output_path / "train.jsonl"), str(output_path / "validation.jsonl")

```

3.2 数据质量过滤

```python class DataQualityFilter: """训练数据质量过滤器"""

def __init__(self):
    from anthropic import Anthropic
    self.client = Anthropic()

def filter_batch(self, examples: list[TrainingExample], threshold: float = 0.7) -> list[TrainingExample]:
    """批量过滤低质量样本"""
    filtered = []
    rejected = 0

    for example in examples:
        score = self._score_example(example)
        if score >= threshold:
            example.quality_score = score
            filtered.append(example)
        else:
            rejected += 1

    print(f"  过滤结果:保留 {len(filtered)}/{len(examples)},拒绝 {rejected} 条低质量样本")
    return filtered

def _score_example(self, example: TrainingExample) -> float:
    """评估单个样本的质量"""
    # 快速规则过滤(不消耗 API)
    if len(example.user.strip()) < 10:
        return 0.0  # 问题太短
    if len(example.assistant.strip()) < 20:
        return 0.1  # 回答太短
    if example.assistant.strip() == example.user.strip():
        return 0.0  # 回答等于问题

    # LLM 质量评估(更准确,但有成本)
    response = self.client.messages.create(
        model="claude-sonnet-4-20250514",
        max_tokens=128,
        messages=[{
            "role": "user",
            "content": f"""评估以下 AI 训练样本的质量(0.0-1.0):

用户:{example.user[:300]} 助手:{example.assistant[:500]}

评分标准: - 回答是否准确且完整(0.4分) - 回答格式是否规范(0.2分) - 是否展示了良好的 Agent 行为(0.2分) - 是否有教学价值(0.2分)

只输出数字分数,如 0.85""" }] )

    try:
        import re
        score_text = response.content[0].text.strip()
        score = float(re.search(r'0?\.\d+|[01]', score_text).group())
        return min(1.0, max(0.0, score))
    except Exception:
        return 0.5  # 解析失败时给中等分

```


四、SFT:监督微调

SFT(Supervised Fine-Tuning,监督微调)是最基础的微调方式:用(输入, 期望输出)对训练模型直接模仿高质量回答。

4.1 使用 OpenAI Fine-tuning API(最简单)

```python

training/openai_ft.py

import openai import time from pathlib import Path

class OpenAIFineTuner: """ 使用 OpenAI Fine-tuning API 进行 SFT 支持 gpt-3.5-turbo、gpt-4o-mini 等模型 """

def __init__(self, api_key: str = None):
    import os
    openai.api_key = api_key or os.getenv("OPENAI_API_KEY")
    self.client = openai.OpenAI()

def upload_dataset(self, file_path: str) -> str:
    """上传训练数据集,返回 file_id"""
    print(f"📤 上传训练数据:{file_path}")
    with open(file_path, "rb") as f:
        response = self.client.files.create(file=f, purpose="fine-tune")
    file_id = response.id
    print(f"✅ 数据上传完成,file_id: {file_id}")
    return file_id

def create_job(
    self,
    train_file_id: str,
    val_file_id: str = None,
    model: str = "gpt-3.5-turbo",
    n_epochs: int = 3,
    batch_size: str = "auto",
    suffix: str = "agent-v1"
) -> str:
    """创建微调任务"""
    print(f"\n🚀 开始微调:{model} × {n_epochs} epochs")

    hyperparams = {"n_epochs": n_epochs, "batch_size": batch_size}

    kwargs = {
        "training_file": train_file_id,
        "model": model,
        "hyperparameters": hyperparams,
        "suffix": suffix
    }
    if val_file_id:
        kwargs["validation_file"] = val_file_id

    job = self.client.fine_tuning.jobs.create(**kwargs)
    print(f"任务 ID:{job.id}")
    return job.id

def monitor_job(self, job_id: str, poll_interval: int = 60) -> dict:
    """监控微调进度,直到完成"""
    print(f"\n⏳ 监控微调进度(每 {poll_interval}s 查询一次)...")

    while True:
        job = self.client.fine_tuning.jobs.retrieve(job_id)
        status = job.status

        # 获取最新事件
        events = self.client.fine_tuning.jobs.list_events(job_id, limit=3)
        for event in events.data[::-1]:
            print(f"  [{event.created_at}] {event.message}")

        if status == "succeeded":
            print(f"\n✅ 微调完成!模型 ID:{job.fine_tuned_model}")
            return {
                "status": "succeeded",
                "model_id": job.fine_tuned_model,
                "trained_tokens": job.trained_tokens
            }

        elif status in ("failed", "cancelled"):
            print(f"\n❌ 微调失败:{job.error}")
            return {"status": status, "error": str(job.error)}

        print(f"  状态:{status},等待 {poll_interval}s...")
        time.sleep(poll_interval)

def evaluate_model(self, model_id: str, test_cases: list[dict]) -> dict:
    """评估微调后的模型"""
    print(f"\n🧪 评估模型:{model_id}")
    results = []

    for case in test_cases:
        response = self.client.chat.completions.create(
            model=model_id,
            messages=[
                {"role": "system", "content": case.get("system", "")},
                {"role": "user", "content": case["user"]}
            ],
            max_tokens=500
        )
        output = response.choices[0].message.content

        # 简单评估:检查关键词是否存在
        expected_keywords = case.get("expected_keywords", [])
        keyword_hits = sum(1 for kw in expected_keywords if kw.lower() in output.lower())
        score = keyword_hits / max(len(expected_keywords), 1)

        results.append({"user": case["user"][:50], "score": score, "output": output[:200]})

    avg_score = sum(r["score"] for r in results) / len(results) if results else 0
    print(f"平均得分:{avg_score:.2f}")
    return {"avg_score": avg_score, "details": results}

完整 SFT 流程

def run_openai_sft_pipeline( train_jsonl: str, val_jsonl: str, model: str = "gpt-3.5-turbo", test_cases: list = None ) -> dict: """端到端的 OpenAI SFT 流程""" ft = OpenAIFineTuner()

# 1. 上传数据
train_id = ft.upload_dataset(train_jsonl)
val_id = ft.upload_dataset(val_jsonl) if val_jsonl else None

# 2. 创建微调任务
job_id = ft.create_job(
    train_file_id=train_id,
    val_file_id=val_id,
    model=model,
    n_epochs=3
)

# 3. 等待完成
result = ft.monitor_job(job_id)

# 4. 评估(如果有测试用例)
if result["status"] == "succeeded" and test_cases:
    eval_result = ft.evaluate_model(result["model_id"], test_cases)
    result["evaluation"] = eval_result

return result

```

4.2 使用 LoRA 微调开源模型

```python

training/lora_ft.py

""" 使用 LoRA 微调开源模型(如 Llama、Mistral、Qwen) 需要:pip install transformers peft datasets bitsandbytes 适合:有 GPU 资源,需要完全控制模型 """

def prepare_lora_training( base_model: str = "Qwen/Qwen2-7B-Instruct", train_data_path: str = "./data/train.jsonl", output_dir: str = "./lora_output", epochs: int = 3, lora_rank: int = 16 # LoRA 秩,越大效果越好但越慢 ): """ 配置并启动 LoRA 微调 单张 A100 (40GB) 可以微调 7B 模型 """ from transformers import ( AutoModelForCausalLM, AutoTokenizer, TrainingArguments, Trainer ) from peft import LoraConfig, get_peft_model, TaskType from datasets import load_dataset import torch

print(f"📦 加载基础模型:{base_model}")
tokenizer = AutoTokenizer.from_pretrained(base_model)

# 4-bit 量化加载(降低显存需求)
from transformers import BitsAndBytesConfig
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.float16,
)

model = AutoModelForCausalLM.from_pretrained(
    base_model,
    quantization_config=bnb_config,
    device_map="auto"
)

# 配置 LoRA
lora_config = LoraConfig(
    task_type=TaskType.CAUSAL_LM,
    r=lora_rank,                    # LoRA 秩
    lora_alpha=lora_rank * 2,       # 缩放因子(通常是 r 的 2 倍)
    target_modules=["q_proj", "v_proj", "k_proj", "o_proj"],  # 目标层
    lora_dropout=0.05,
    bias="none",
)

model = get_peft_model(model, lora_config)
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
total_params = sum(p.numel() for p in model.parameters())
print(f"可训练参数:{trainable_params:,} / {total_params:,} ({trainable_params/total_params:.2%})")

# 加载数据集
def format_example(example):
    """将样本转换为模型输入格式"""
    messages = example.get("messages", [])
    text = tokenizer.apply_chat_template(messages, tokenize=False)
    return {"text": text}

dataset = load_dataset("json", data_files={"train": train_data_path})
formatted = dataset["train"].map(format_example)

# 训练配置
training_args = TrainingArguments(
    output_dir=output_dir,
    num_train_epochs=epochs,
    per_device_train_batch_size=4,
    gradient_accumulation_steps=4,  # 等效 batch_size=16
    learning_rate=2e-4,
    fp16=True,
    logging_steps=10,
    save_steps=100,
    save_total_limit=3,
    warmup_ratio=0.05,
    lr_scheduler_type="cosine",
)

# 开始训练
from trl import SFTTrainer
trainer = SFTTrainer(
    model=model,
    train_dataset=formatted,
    args=training_args,
    tokenizer=tokenizer,
    dataset_text_field="text",
    max_seq_length=2048,
)

print("\n🚀 开始 LoRA 微调...")
trainer.train()

# 保存 LoRA 权重
model.save_pretrained(output_dir)
tokenizer.save_pretrained(output_dir)
print(f"\n✅ LoRA 权重已保存:{output_dir}")

return output_dir

```


五、RLHF:基于人类反馈的强化学习

SFT 让模型模仿示例,RLHF 让模型学会"什么样的输出人类更喜欢"。

```python

training/rlhf.py

""" RLHF 的简化版本:DPO(Direct Preference Optimization) 比完整 RLHF 更简单,效果接近 需要:pip install trl transformers """

from dataclasses import dataclass

@dataclass class PreferenceExample: """偏好对比样本(DPO 训练数据格式)""" prompt: str # 用户输入 chosen: str # 人类认为更好的回答 rejected: str # 人类认为较差的回答 reason: str = "" # 为什么 chosen 更好(可选,用于质量过滤)

class PreferenceDataCollector: """ 收集偏好数据 通常通过以下方式: 1. 人工标注:给两个回答让人选择哪个更好 2. AI 辅助标注:用强模型评判,人工抽样验证 3. 生产反馈:用户的点赞/点踩行为 """

def collect_from_ab_test(
    self,
    prompts: list[str],
    model_a: str,  # 基础模型
    model_b: str,  # 候选模型
    human_annotator_func = None  # 人工标注函数(或 AI 替代)
) -> list[PreferenceExample]:
    """
    通过 A/B 测试收集偏好数据
    """
    from anthropic import Anthropic
    client = Anthropic()
    examples = []

    for prompt in prompts:
        # 获取两个模型的回答
        def get_response(model):
            resp = client.messages.create(
                model=model,
                max_tokens=1000,
                messages=[{"role": "user", "content": prompt}]
            )
            return resp.content[0].text

        response_a = get_response(model_a)
        response_b = get_response(model_b)

        # 人工或 AI 标注哪个更好
        if human_annotator_func:
            winner = human_annotator_func(prompt, response_a, response_b)
        else:
            winner = self._ai_judge(prompt, response_a, response_b, client)

        if winner == "A":
            examples.append(PreferenceExample(
                prompt=prompt, chosen=response_a, rejected=response_b
            ))
        elif winner == "B":
            examples.append(PreferenceExample(
                prompt=prompt, chosen=response_b, rejected=response_a
            ))
        # winner == "TIE" 时跳过(偏好不明确的样本效果差)

    return examples

def _ai_judge(self, prompt: str, response_a: str, response_b: str, client) -> str:
    """使用 Claude 判断哪个回答更好(AI 辅助标注)"""
    import json, re
    response = client.messages.create(
        model="claude-sonnet-4-20250514",
        max_tokens=256,
        messages=[{
            "role": "user",
            "content": f"""对于以下问题,判断回答 A 还是 B 更好:

问题:{prompt}

回答 A:{response_a[:500]}

回答 B:{response_b[:500]}

评判维度: 1. 准确性(最重要) 2. 完整性 3. 清晰度 4. 格式规范性

以 JSON 输出:{{"winner": "A" 或 "B" 或 "TIE", "reason": "简短原因"}}""" }] )

    text = response.content[0].text
    match = re.search(r'\{.*\}', text, re.DOTALL)
    if match:
        result = json.loads(match.group())
        return result.get("winner", "TIE")
    return "TIE"

def run_dpo_training( preference_data: list[PreferenceExample], base_model: str = "Qwen/Qwen2-7B-Instruct", output_dir: str = "./dpo_output" ): """ 使用 DPO(Direct Preference Optimization)训练 比 RLHF 更稳定,不需要奖励模型 """ from trl import DPOTrainer, DPOConfig from transformers import AutoModelForCausalLM, AutoTokenizer from datasets import Dataset import torch

# 准备数据集
data_dict = {
    "prompt": [e.prompt for e in preference_data],
    "chosen": [e.chosen for e in preference_data],
    "rejected": [e.rejected for e in preference_data],
}
dataset = Dataset.from_dict(data_dict)

# 加载模型
model = AutoModelForCausalLM.from_pretrained(
    base_model, torch_dtype=torch.float16, device_map="auto"
)
tokenizer = AutoTokenizer.from_pretrained(base_model)

# DPO 训练配置
training_args = DPOConfig(
    output_dir=output_dir,
    num_train_epochs=1,
    per_device_train_batch_size=2,
    gradient_accumulation_steps=8,
    learning_rate=5e-7,            # DPO 通常用更小的学习率
    beta=0.1,                      # KL 惩罚系数(防止偏离基础模型太多)
    fp16=True,
    logging_steps=10,
)

trainer = DPOTrainer(
    model=model,
    ref_model=None,               # 使用基础模型作为参考(自动处理)
    args=training_args,
    train_dataset=dataset,
    tokenizer=tokenizer,
)

print("🚀 开始 DPO 训练...")
trainer.train()
trainer.save_model(output_dir)
print(f"✅ DPO 模型已保存:{output_dir}")

```


六、Agent 专项微调技巧

6.1 工具调用格式对齐

```python

创建专门针对工具调用的训练样本

TOOL_CALL_TRAINING_TEMPLATE = """ 你是一个 AI 助手,可以使用以下工具: - web_search(query): 搜索互联网 - calculate(expression): 数学计算 - execute_python(code): 执行 Python 代码

当需要工具时,以如下格式输出: {{"name": "工具名", "arguments": {{"参数": "值"}}}}

工具结果会以如下格式返回: 结果内容

获得足够信息后,给出最终答案。 """

tool_call_examples = [ TrainingExample( system=TOOL_CALL_TRAINING_TEMPLATE, user="苹果公司今天的股价是多少?", assistant="""我需要搜索实时股价信息。 {"name": "web_search", "arguments": {"query": "AAPL stock price today"}} AAPL: $182.63 (+1.2%)

苹果公司(AAPL)今日股价为 $182.63,较昨日上涨 1.2%。""" ), # ... 更多示例 ] ```

6.2 推理格式对齐

```python

训练模型输出结构化的 CoT 推理

COT_TRAINING_EXAMPLES = [ TrainingExample( system="你是一个严谨的分析师,在给出结论前先进行系统性推理。", user="Python 的 GIL 对多线程性能有什么影响?", assistant="""分析过程:

理解问题: 需要分析 GIL(全局解释器锁)对 Python 多线程的具体影响。

关键事实: 1. GIL 是 CPython 的实现细节,每次只允许一个线程执行 Python 字节码 2. I/O 操作会释放 GIL(文件读写、网络请求等) 3. CPU 密集型操作不释放 GIL

推理: - I/O 密集型任务(Web 请求、文件操作):多线程有效,因为等待 I/O 时 GIL 被释放,其他线程可以运行 - CPU 密集型任务(数学计算、数据处理):多线程几乎无效,GIL 让线程串行执行,甚至因为线程切换开销而比单线程更慢

结论: GIL 对 Python 多线程的影响是双面的: - ✅ I/O 密集型任务:多线程提速显著 - ❌ CPU 密集型任务:多线程无效,应改用多进程(multiprocessing)或异步(asyncio)""" ) ] ```


七、微调效果评估

```python class FineTuneEvaluator: """微调效果评估器"""

def compare_base_vs_finetuned(
    self,
    base_model_func,
    finetuned_model_func,
    test_cases: list[dict]
) -> dict:
    """对比基础模型和微调后模型的效果"""
    from evaluation.llm_judge import LLMJudge
    judge = LLMJudge()

    base_scores = []
    ft_scores = []

    for case in test_cases:
        prompt = case["input"]
        expected = case.get("expected_keywords", [])

        base_output = base_model_func(prompt)
        ft_output = finetuned_model_func(prompt)

        # 使用 LLM-as-Judge 评估
        base_score = judge.judge_relevance(prompt, base_output).score
        ft_score = judge.judge_relevance(prompt, ft_output).score

        base_scores.append(base_score)
        ft_scores.append(ft_score)

        print(f"\n问题:{prompt[:50]}...")
        print(f"  基础模型:{base_score:.2f} | 微调后:{ft_score:.2f} | {'✅ 提升' if ft_score > base_score else '❌ 下降'}")

    avg_base = sum(base_scores) / len(base_scores)
    avg_ft = sum(ft_scores) / len(ft_scores)
    improvement = (avg_ft - avg_base) / avg_base

    return {
        "base_avg_score": round(avg_base, 3),
        "finetuned_avg_score": round(avg_ft, 3),
        "improvement": f"{improvement:+.1%}",
        "is_better": avg_ft > avg_base,
        "recommendation": "✅ 建议部署微调模型" if avg_ft > avg_base + 0.05 else "⚠️ 提升不显著,评估是否值得"
    }

```


八、微调 vs Prompt 工程决策树

你遇到的问题是什么? │ ├── 输出格式不稳定 │ └── 先试:Few-Shot + 结构化输出约束 │ → 仍不满足:SFT(格式对齐) │ ├── 领域知识不足 │ └── 先试:RAG(知识检索) │ → 专有术语/推理模式问题:SFT │ ├── 语气/风格不符合品牌要求 │ └── 先试:详细的系统提示词 + Few-Shot │ → 仍不满足:SFT(风格对齐) │ ├── 推理能力不足 │ └── 先试:CoT / ToT + 换更大的模型 │ → 特定推理模式:SFT │ ├── 用户更喜欢另一种回答方式 │ └── 先试:收集反馈优化 Prompt │ → 有大量偏好数据:DPO/RLHF │ └── 延迟/成本问题 └── 先试:换小模型 + 优化 Prompt → 质量不够:SFT 小模型 ≈ 大模型效果


九、总结

微调的核心认知:

微调是放大器,不是修复工具:好数据 + 微调 = 更好的模型;坏数据 + 微调 = 更稳定地犯错。数据质量是一切的基础。

SFT vs DPO 的选择

  • SFT:知道"正确答案是什么",有标注好的(输入,输出)对
  • DPO:知道"哪个答案更好",有偏好对比数据(chosen vs rejected)
  • 实践中:先做 SFT,再用 DPO 精调对齐

什么时候停止 Prompt 工程转向微调:当你已经有 500+ 条高质量的"这是我希望模型输出的"样本,而且这个模式足够稳定可以泛化,此时微调的 ROI 才是正的。

下一篇是进阶专题篇的倒数第二篇——垂直领域 Agent 实战,用代码 Agent、数据分析 Agent、客服 Agent 三个完整案例,把系列所有知识综合运用。


下期预告:AI Agent 系列(二十)—— 垂直领域 Agent 实战:代码、数据分析与客服 Agent 完整案例

作者:[你的署名] 转载:请注明出处和系列链接

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-05-22 08:22:28 HTTP/1.1 GET : https://www.yeyulingfeng.com/a/652953.html
  2. 运行时间 : 0.311089s [ 吞吐率:3.21req/s ] 内存消耗:4,768.84kb 文件加载:145
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=6ca87a9ecc49189f4ad4c6bcbcf42688
  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.000954s ] mysql:host=127.0.0.1;port=3306;dbname=wenku;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.001803s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000682s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000688s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.001330s ]
  6. SELECT * FROM `set` [ RunTime:0.000594s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.001452s ]
  8. SELECT * FROM `article` WHERE `id` = 652953 LIMIT 1 [ RunTime:0.001228s ]
  9. UPDATE `article` SET `lasttime` = 1779409348 WHERE `id` = 652953 [ RunTime:0.110457s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 64 LIMIT 1 [ RunTime:0.007114s ]
  11. SELECT * FROM `article` WHERE `id` < 652953 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.002405s ]
  12. SELECT * FROM `article` WHERE `id` > 652953 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.002761s ]
  13. SELECT * FROM `article` WHERE `id` < 652953 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.003212s ]
  14. SELECT * FROM `article` WHERE `id` < 652953 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.002425s ]
  15. SELECT * FROM `article` WHERE `id` < 652953 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.002452s ]
0.313350s