feat: deepseek summary agent + clean old memory logs + merge prep

This commit is contained in:
sj
2026-08-09 09:04:27 +08:00
parent 7399b0bf14
commit 9c38f32d52
34 changed files with 98469 additions and 2378 deletions
+87 -12
View File
@@ -1,10 +1,10 @@
#!/home/xzq/miniconda3/envs/test4py311/bin/python
"""Scope-aware whole-job summary stage.
"""Scope-aware whole-job summary and DeepSeek report stage.
Summary is an objective result index and quality-control layer. It reads all
stage manifests in a job, groups them by scope_id, extracts key metrics and
artifacts, and writes machine-readable and human-readable summaries. It does
not perform deep biological interpretation.
The deterministic layer first builds a traceable manifest/artifact index. By
default that evidence is then passed to DeepSeek to produce the human-readable
Chinese report. The evidence index remains a separate artifact so generated
prose can always be audited against local results.
"""
import argparse
@@ -16,6 +16,10 @@ from pathlib import Path
from typing import Any, Dict, Iterable, List, Optional, Tuple
PROJECT_ROOT = Path(__file__).resolve().parents[2]
if str(PROJECT_ROOT) not in sys.path:
sys.path.insert(0, str(PROJECT_ROOT))
CONDA_BIN = "/home/xzq/miniconda3/envs/test4py311/bin"
if CONDA_BIN not in os.environ.get("PATH", ""):
os.environ["PATH"] = CONDA_BIN + ":" + os.environ.get("PATH", "")
@@ -256,6 +260,10 @@ def main():
parser.add_argument("--scope-id", help="optional explicit scope_id filter")
parser.add_argument("--force", action="store_true", help="overwrite existing results")
parser.add_argument("--log-file", help="log file path")
parser.add_argument("--no-deepseek", action="store_true", help="write only the deterministic evidence index")
parser.add_argument("--framework", help="optional Markdown framework for the DeepSeek report")
parser.add_argument("--deepseek-model", default="", help="optional DeepSeek model override")
parser.add_argument("--deepseek-max-tokens", type=int, default=16000)
args = parser.parse_args()
manifest_path = Path(args.manifest).expanduser().resolve() if args.manifest else None
@@ -284,11 +292,11 @@ def main():
artifact_rows = [row for item in summaries for row in item["artifact_rows"]]
checks = build_checks(summaries)
report = final_dir / f"{prefix}.summary_report.md"
evidence_index = final_dir / f"{prefix}.summary_evidence_index.md"
files_tsv = final_dir / f"{prefix}.summary.files.tsv"
manifest_out = final_dir / f"{prefix}.summary.manifest.json"
write_files_tsv(files_tsv, artifact_rows)
write_report(report, prefix, summaries, checks, files_tsv)
write_report(evidence_index, prefix, summaries, checks, files_tsv)
manifest_data = {
"manifest_version": "1.0",
@@ -306,22 +314,24 @@ def main():
"summaries": summaries,
"checks": checks,
"artifacts": {
"summary_report": {"path": f"final/{report.name}", "type": "markdown", "size": report.stat().st_size},
"summary_evidence_index": {"path": f"final/{evidence_index.name}", "type": "markdown", "size": evidence_index.stat().st_size},
"files_tsv": {"path": f"final/{files_tsv.name}", "type": "tsv", "size": files_tsv.stat().st_size},
},
}
manifest_out.write_text(json.dumps(manifest_data, indent=2, ensure_ascii=False), encoding="utf-8")
scoped_manifest = None
scoped_data = None
if scope_id:
scoped_items = [x for x in summaries if x["scope_id"] == scope_id]
scoped_rows = [row for x in scoped_items for row in x["artifact_rows"]]
scoped_checks = [x for x in checks if x["scope_id"] in {scope_id, "all"}]
token = sanitize_token(scope_id)
scoped_report = final_dir / f"{prefix}.{token}.summary_report.md"
scoped_evidence_index = final_dir / f"{prefix}.{token}.summary_evidence_index.md"
scoped_files = final_dir / f"{prefix}.{token}.summary.files.tsv"
scoped_manifest = final_dir / f"{prefix}.{token}.summary.manifest.json"
write_files_tsv(scoped_files, scoped_rows)
write_report(scoped_report, prefix, scoped_items, scoped_checks, scoped_files)
write_report(scoped_evidence_index, prefix, scoped_items, scoped_checks, scoped_files)
scoped_data = dict(manifest_data)
scoped_data.update({
"scope_id": scope_id,
@@ -334,14 +344,79 @@ def main():
"summaries": scoped_items,
"checks": scoped_checks,
"artifacts": {
"summary_report": {"path": f"final/{scoped_report.name}", "type": "markdown", "size": scoped_report.stat().st_size},
"summary_evidence_index": {"path": f"final/{scoped_evidence_index.name}", "type": "markdown", "size": scoped_evidence_index.stat().st_size},
"files_tsv": {"path": f"final/{scoped_files.name}", "type": "tsv", "size": scoped_files.stat().st_size},
},
})
scoped_manifest.write_text(json.dumps(scoped_data, indent=2, ensure_ascii=False), encoding="utf-8")
if args.no_deepseek:
fallback_report = final_dir / (
f"{prefix}.{sanitize_token(scope_id)}.summary_report.md" if scope_id else f"{prefix}.summary_report.md"
)
source_index = scoped_evidence_index if scope_id else evidence_index
fallback_report.write_text(source_index.read_text(encoding="utf-8"), encoding="utf-8")
target_manifest = scoped_manifest if scope_id and scoped_manifest else manifest_out
target_data = read_json(target_manifest) or manifest_data
target_data.setdefault("artifacts", {})["summary_report"] = {
"path": f"final/{fallback_report.name}",
"type": "markdown",
"size": fallback_report.stat().st_size,
"generation": "deterministic_no_deepseek",
}
target_data["deepseek_generation"] = {"status": "skipped", "reason": "--no-deepseek"}
target_manifest.write_text(json.dumps(target_data, indent=2, ensure_ascii=False), encoding="utf-8")
else:
try:
from gfa_core.mas.agents.deepseek_summary import generate_deepseek_summary
result = generate_deepseek_summary(
final_dir=final_dir,
prefix=prefix,
job_id=workspace.name,
summaries=summaries,
scope_id=scope_id,
framework_path=Path(args.framework).expanduser() if args.framework else None,
model=args.deepseek_model,
max_tokens=max(4096, int(args.deepseek_max_tokens)),
)
effective_scope = str(result.get("scope_id") or "")
target_manifest = scoped_manifest if scope_id and scoped_manifest else manifest_out
target_data = read_json(target_manifest) or manifest_data
report_path = Path(result["report_path"])
evidence_path = Path(result["evidence_path"])
metadata_path = Path(result["metadata_path"])
target_data.setdefault("artifacts", {}).update({
"summary_report": {
"path": f"final/{report_path.name}", "type": "markdown", "size": report_path.stat().st_size,
"generation": "deepseek_api",
},
"summary_evidence": {
"path": f"final/{evidence_path.name}", "type": "json", "size": evidence_path.stat().st_size,
},
"deepseek_metadata": {
"path": f"final/{metadata_path.name}", "type": "json", "size": metadata_path.stat().st_size,
},
})
target_data["deepseek_generation"] = {
"status": "success",
"scope_id": effective_scope,
"provider": result["metadata"].get("provider"),
"model": result["metadata"].get("model"),
"validation": result["metadata"].get("validation"),
}
target_manifest.write_text(json.dumps(target_data, indent=2, ensure_ascii=False), encoding="utf-8")
except Exception as exc:
target_manifest = scoped_manifest if scope_id and scoped_manifest else manifest_out
target_data = read_json(target_manifest) or manifest_data
target_data["status"] = "failed"
target_data["deepseek_generation"] = {"status": "failed", "error": str(exc)[:2000]}
target_manifest.write_text(json.dumps(target_data, indent=2, ensure_ascii=False), encoding="utf-8")
print(f"Error: DeepSeek summary generation failed: {exc}", file=sys.stderr)
sys.exit(2)
print("Summary complete")
print(f" - {report}")
print(f" - {evidence_index}")
print(f" - {files_tsv}")
print(f" - {manifest_out}")
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff