new-human
feat: 支持真实CSV数据训练与模型推理闭环
0bb564a
from __future__ import annotations
import json
from pathlib import Path
from typing import Any, Dict, List
from .base import BaseAgent
from ..config import TrainConfig
class ReporterAgent(BaseAgent):
name = "ReporterAgent"
def run(self, *, cfg: TrainConfig, dataset: Any, summary: Dict[str, Any]) -> None:
attempt = int(summary.get("attempts", 1))
model = self.ctx.store.read_json(f"model.attempt{attempt}.json")
w: List[float] = list(model["w"])
pairs = list(enumerate(w))
pairs.sort(key=lambda x: abs(float(x[1])), reverse=True)
top_k = max(1, int(cfg.report_top_k_features))
feature_names = getattr(dataset, "feature_names", None)
top = []
for i, v in pairs[:top_k]:
fname = feature_names[i] if feature_names and i < len(feature_names) else str(i)
top.append({"feature": fname, "weight": float(v)})
report_obj = {
"run_dir": str(self.ctx.store.run_dir),
"attempts": int(summary.get("attempts", attempt)),
"final_cfg": cfg.to_dict(),
"eval": summary.get("eval", {}),
"top_features": top,
}
md_lines: List[str] = []
md_lines.append("# 训练报告")
md_lines.append("")
md_lines.append(f"- 运行目录:{self.ctx.store.run_dir}")
md_lines.append(f"- 尝试次数:{report_obj['attempts']}")
md_lines.append("")
md_lines.append("## 最终指标")
md_lines.append("")
ev = report_obj["eval"] or {}
md_lines.append(f"- train_loss: {ev.get('train_loss')}")
md_lines.append(f"- train_acc: {ev.get('train_acc')}")
md_lines.append(f"- val_loss: {ev.get('val_loss')}")
md_lines.append(f"- val_acc: {ev.get('val_acc')}")
md_lines.append("")
md_lines.append("## 自动调试结果")
md_lines.append("")
md_lines.append("- 查看 debug.attempt*.json 可回放每次诊断与修复建议")
md_lines.append("")
md_lines.append("## 模型权重(按绝对值 Top)")
md_lines.append("")
md_lines.append("| feature | weight |")
md_lines.append("|---:|---:|")
for t in top:
md_lines.append(f"| {t['feature']} | {t['weight']:.6f} |")
md_lines.append("")
md_lines.append("## 复现")
md_lines.append("")
md_lines.append("本次运行的最终配置已落盘到 config.json。")
md_lines.append("")
self.ctx.store.write_json("report.json", report_obj)
self.ctx.store.write_text("report.md", "\n".join(md_lines))
self.emit(receiver="Orchestrator", kind="report_ready", payload={"report": "report.md"})