Phase 0-2: Schema cleanup, typed relations, event-driven automation

- Phase 0: AGENTS.md cleanup (dedup quotes, renumber sections, merge qmd)
- Phase 1: typed relations (manage-relations.py, graph-search.py, check-staleness.py, detect-conflicts.py)
- Phase 2: frontmatter validator, weekly lint, knowledge promotion, git hooks
- Fix .gitignore to track tools/ and .githooks/
- Fix git remote URL (remove plaintext token)
- New wiki pages: 504 pages, 34 raw sources
This commit is contained in:
hehaiguang1123
2026-07-01 08:05:43 +08:00
parent e544d6e04a
commit a6f05ab2d5
1067 changed files with 522992 additions and 819 deletions
@@ -0,0 +1,611 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
文献质量评估报告生成器
功能:
1. 交互式生成单篇文献评估报告
2. 批量生成多篇文献评估报告
3. 自动计算部分分数(时效性、信源权威性)
4. 手动输入其他维度分数
5. 生成标准OFM格式评估报告
使用方式:
python 质量评估报告生成器.py # 交互式单篇评估
python 质量评估报告生成器.py --batch # 批量评估(从文献库JSON读取)
python 质量评估报告生成器.py --help # 查看帮助
"""
import sys
import os
import json
import argparse
from datetime import datetime
from pathlib import Path
# 配置路径
BASE_DIR = Path(__file__).parent.parent
LIBRARY_DIR = BASE_DIR / "文献库"
LIBRARY_JSON = LIBRARY_DIR / "文献索引数据库.json"
OUTPUT_DIR = BASE_DIR / "文献库"
class QualityAssessment:
"""文献质量评估系统"""
def __init__(self):
self.current_year = datetime.now().year
self.assessment_dimensions = {
"timeliness": {"name": "时效性", "max_score": 15},
"source_authority": {"name": "信源权威性", "max_score": 20},
"data_quality": {"name": "数据质量", "max_score": 20},
"method_rigor": {"name": "方法严谨性", "max_score": 20},
"empirical_basis": {"name": "实证基础", "max_score": 20},
"theoretical_framework": {"name": "理论框架", "max_score": 15},
"impact": {"name": "影响力", "max_score": 15}
}
def calculate_timeliness_score(self, year):
"""
计算时效性分数(15分制)
规则:
- 2026年(当年):15分
- 2025年:12分
- 2024年:9分
- 2023年:6分
- 2022年及以前:3分
"""
age = self.current_year - year
if age == 0:
return 15
elif age == 1:
return 12
elif age == 2:
return 9
elif age == 3:
return 6
else:
return 3
def calculate_source_authority(self, source_info):
"""
计算信源权威性分数(20分制)
规则:
- Nature/Science/Cell20分
- 顶刊/顶会(如Scientific Reports、Computers and Education、AIED):18分
- 一区期刊(如Frontiers系列、IEEE/ACM):16分
- 顶级会议(如arXiv预印本):16分
- ERIC/官方报告:18分
- 其他知名期刊:14分
- 未明确来源:12分
"""
if not source_info:
return 12
source_lower = source_info.lower()
# 顶级期刊
if any(j in source_lower for j in ["nature", "science", "cell"]):
return 20
# 顶刊/顶会
if any(j in source_lower for j in ["scientific reports", "computers and education", "aied", "eric"]):
return 18
# 一区期刊/顶会
if any(j in source_lower for j in ["frontiers", "ieee", "acm", "arxiv", "preprint"]):
return 16
# 官方报告/政策文件
if any(j in source_lower for j in ["report", "guidelines", "whitepaper"]):
return 18
# 知名期刊
if any(j in source_lower for j in ["springer", "taylor", "elsevier", "sage"]):
return 14
# 未明确来源
return 12
def input_score(self, dimension_key, auto_score=None):
"""
交互式输入分数
Args:
dimension_key: 维度键值
auto_score: 自动计算的分数(如有)
Returns:
int: 输入的分数
"""
dim = self.assessment_dimensions[dimension_key]
dim_name = dim["name"]
max_score = dim["max_score"]
if auto_score is not None:
print(f"\n📊 {dim_name}{max_score}分):自动计算得 {auto_score}")
confirm = input("是否确认?(Y/n,默认Y): ").strip().lower()
if confirm != "n":
return auto_score
while True:
try:
score = int(input(f"📊 请输入 {dim_name} 分数(0-{max_score}分): "))
if 0 <= score <= max_score:
return score
else:
print(f"❌ 分数必须在 0-{max_score} 之间,请重新输入!")
except ValueError:
print("❌ 请输入有效的数字!")
def generate_single_assessment(self):
"""
交互式生成单篇文献评估报告
"""
print("\n" + "="*60)
print("📚 文献质量评估报告生成器")
print("="*60)
# 输入基本信息
print("\n📝 第一步:输入文献基本信息")
print("-"*60)
paper_id = input("文献ID(如 Entry 1 输入 1,或留空自动编号): ").strip()
title = input("文献标题: ").strip()
authors = input("作者(多个作者用逗号分隔): ").strip()
source = input("来源/期刊/会议: ").strip()
year_str = input("发表年份(如 2025,留空默认当年): ").strip()
pdf_path = input(f"PDF路径(相对于 {LIBRARY_DIR},如 PDFs/paper.pdf: ").strip()
# 默认值处理
if not paper_id:
# 自动生成ID(简单策略:使用时间戳)
paper_id = f"auto-{datetime.now().strftime('%Y%m%d%H%M%S')}"
year = self.current_year if not year_str else int(year_str)
# 自动计算部分分数
print("\n📊 第二步:自动计算分数")
print("-"*60)
timeliness_score = self.calculate_timeliness_score(year)
source_authority_score = self.calculate_source_authority(source)
print(f"✅ 时效性分数:{timeliness_score}/15")
print(f"✅ 信源权威性分数:{source_authority_score}/20")
# 手动输入其他维度分数
print("\n📊 第三步:输入其他维度分数")
print("-"*60)
scores = {
"timeliness": timeliness_score,
"source_authority": source_authority_score,
"data_quality": self.input_score("data_quality"),
"method_rigor": self.input_score("method_rigor"),
"empirical_basis": self.input_score("empirical_basis"),
"theoretical_framework": self.input_score("theoretical_framework"),
"impact": self.input_score("impact")
}
# 计算总分和质量等级
total_score = sum(scores.values())
quality_grade = self.calculate_quality_grade(total_score)
# 输入核心发现与价值
print("\n📝 第四步:核心发现与价值(选填,可留空)")
print("-"*60)
key_findings = []
print("输入核心发现(留空结束,最多3条):")
for i in range(1, 4):
finding = input(f" {i}. ").strip()
if not finding:
break
key_findings.append(finding)
strengths = []
print("\n输入文献优势(留空结束,最多3条):")
for i in range(1, 4):
strength = input(f" {i}. ").strip()
if not strength:
break
strengths.append(strength)
limitations = []
print("\n输入文献局限(留空结束,最多3条):")
for i in range(1, 4):
limitation = input(f" {i}. ").strip()
if not limitation:
break
limitations.append(limitation)
# 输入适用场景与使用建议
print("\n📝 第五步:适用场景与使用建议(选填,可留空)")
print("-"*60)
use_cases = []
print("输入适用场景(留空结束,最多3条):")
for i in range(1, 4):
use_case = input(f" {i}. ").strip()
if not use_case:
break
use_cases.append(use_case)
recommendations = []
print("\n输入使用建议(留空结束,最多3条):")
for i in range(1, 4):
recommendation = input(f" {i}. ").strip()
if not recommendation:
break
recommendations.append(recommendation)
# 生成报告
report_content = self.generate_report_content(
paper_id=paper_id,
title=title,
authors=authors,
source=source,
year=year,
pdf_path=pdf_path,
scores=scores,
total_score=total_score,
quality_grade=quality_grade,
key_findings=key_findings,
strengths=strengths,
limitations=limitations,
use_cases=use_cases,
recommendations=recommendations
)
# 保存报告
output_filename = f"论文质量评估-{paper_id}-{datetime.now().strftime('%Y%m%d')}.md"
output_path = OUTPUT_DIR / output_filename
with open(output_path, "w", encoding="utf-8") as f:
f.write(report_content)
print(f"\n✅ 评估报告已生成:{output_path}")
print(f"✅ 总分:{total_score}/105,质量等级:{quality_grade}")
return output_path
def calculate_quality_grade(self, total_score):
"""
根据总分计算质量等级
规则:
- A+级:95分及以上
- A级:90-94分
- A-级:85-89分
- B+级:80-84分
- B级:70-79分
- B-级:60-69分
- C级:60分以下
"""
if total_score >= 95:
return "A+级"
elif total_score >= 90:
return "A级"
elif total_score >= 85:
return "A-级"
elif total_score >= 80:
return "B+级"
elif total_score >= 70:
return "B级"
elif total_score >= 60:
return "B-级"
else:
return "C级"
def generate_report_content(self, paper_id, title, authors, source, year, pdf_path,
scores, total_score, quality_grade,
key_findings, strengths, limitations,
use_cases, recommendations):
"""
生成评估报告内容(OFM格式)
"""
# 构建评估维度表格
dimensions_table = "| 评估维度 | 满分 | 得分 | 说明 |\n"
dimensions_table += "|---------|------|------|------|\n"
for key, dim in self.assessment_dimensions.items():
dim_name = dim["name"]
max_score = dim["max_score"]
score = scores[key]
# 添加说明
if key == "timeliness":
note = f"发表年份:{year}"
elif key == "source_authority":
note = f"来源:{source}"
else:
note = "手动评估"
dimensions_table += f"| {dim_name} | {max_score} | {score} | {note} |\n"
dimensions_table += f"| **总分** | **105** | **{total_score}** | **质量等级:{quality_grade}** |\n"
# 生成报告内容
content = f"""---
created: {datetime.now().strftime('%Y-%m-%d')}
title: 论文质量评估 - {title}
tags: [质量评估, {quality_grade}]
source: {source}
category: quality_assessment
---
# 论文质量评估报告
## 文献基本信息
| 字段 | 内容 |
|------|------|
| **文献ID** | {paper_id} |
| **标题** | {title} |
| **作者** | {authors} |
| **来源** | {source} |
| **年份** | {year} |
| **PDF路径** | `{pdf_path if pdf_path else '未指定'}` |
| **评估日期** | {datetime.now().strftime('%Y-%m-%d')} |
---
## 质量评估得分
{dimensions_table}
---
## 核心发现与价值
"""
# 添加核心发现
if key_findings:
for i, finding in enumerate(key_findings, 1):
content += f"{i}. {finding}\n"
else:
content += "> 未提供核心发现\n"
content += "\n"
# 添加文献优势
if strengths:
content += "### 优势\n\n"
for i, strength in enumerate(strengths, 1):
content += f"{i}. {strength}\n"
content += "\n"
# 添加文献局限
if limitations:
content += "### 局限\n\n"
for i, limitation in enumerate(limitations, 1):
content += f"{i}. {limitation}\n"
content += "\n"
# 添加适用场景与使用建议
content += "---\n\n## 适用场景与使用建议\n\n"
if use_cases:
content += "### 适用场景\n\n"
for i, use_case in enumerate(use_cases, 1):
content += f"{i}. {use_case}\n"
content += "\n"
if recommendations:
content += "### 使用建议\n\n"
for i, recommendation in enumerate(recommendations, 1):
content += f"{i}. {recommendation}\n"
content += "\n"
# 添加质量等级说明
content += "---\n\n## 质量等级说明\n\n"
content += f"**本次评估总分:{total_score}/105**\n\n"
content += f"**质量等级:{quality_grade}**\n\n"
content += f"**评分标准**\n"
content += f"- A+级(≥95分):顶尖文献,可作为核心引用源\n"
content += f"- A级(90-94分):高质量文献,可作为重要引用源\n"
content += f"- A-级(85-89分):良好文献,可作为辅助引用源\n"
content += f"- B+级(80-84分):合格文献,特定场景有用\n"
content += f"- B级(70-79分):一般文献,谨慎使用\n"
content += f"- B-级(60-69分):较差文献,尽量少用\n"
content += f"- C级(<60分):低质量文献,不建议引用\n"
return content
def generate_batch_assessments(self):
"""
批量生成多篇文献评估报告(从文献库JSON读取)
"""
print("\n" + "="*60)
print("📚 批量文献质量评估")
print("="*60)
# 检查文献库JSON是否存在
if not LIBRARY_JSON.exists():
print(f"❌ 文献库文件不存在:{LIBRARY_JSON}")
print("请先运行文献库管理器创建文献库。")
return
# 读取文献库JSON
with open(LIBRARY_JSON, "r", encoding="utf-8") as f:
library_data = json.load(f)
if "entries" not in library_data:
print("❌ 文献库格式错误:缺少 'entries' 字段")
return
entries = library_data["entries"]
# 过滤未评估的文献
unassessed = []
for entry in entries:
if "quality_assessment" not in entry or not entry["quality_assessment"]:
unassessed.append(entry)
if not unassessed:
print("✅ 所有文献已评估完毕!")
return
print(f"\n📊 发现 {len(unassessed)} 篇未评估文献")
print("-"*60)
# 列出未评估文献
for i, entry in enumerate(unassessed[:10], 1):
print(f"{i}. [{entry['id']}] {entry['title'][:60]}...")
if len(unassessed) > 10:
print(f"... 还有 {len(unassessed) - 10} 篇未显示")
# 询问是否继续
confirm = input(f"\n是否开始批量评估前 {min(10, len(unassessed))} 篇文献?(Y/n,默认Y): ").strip().lower()
if confirm == "n":
return
# 批量评估(限制前10篇,避免时间过长)
for entry in unassessed[:10]:
print(f"\n{'='*60}")
print(f"📚 评估文献 [{entry['id']}]")
print(f"{'='*60}")
print(f"标题: {entry['title']}")
print(f"作者: {entry['authors']}")
print(f"来源: {entry['source']}")
print(f"年份: {entry.get('year', '未知')}")
# 自动计算分数
year = entry.get("year", self.current_year)
timeliness_score = self.calculate_timeliness_score(year)
source_authority_score = self.calculate_source_authority(entry.get("source", ""))
print(f"\n✅ 自动计算:")
print(f" - 时效性分数:{timeliness_score}/15")
print(f" - 信源权威性分数:{source_authority_score}/20")
# 简化版批量评估:只输入总分
print(f"\n📊 请输入其他维度分数(简化版,直接输入5个维度的平均分):")
avg_score = input(" 数据质量/方法严谨性/实证基础/理论框架/影响力 的平均分(0-20): ").strip()
try:
avg_score = int(avg_score)
if not (0 <= avg_score <= 20):
print("❌ 分数无效,跳过此篇")
continue
except ValueError:
print("❌ 输入无效,跳过此篇")
continue
scores = {
"timeliness": timeliness_score,
"source_authority": source_authority_score,
"data_quality": avg_score,
"method_rigor": avg_score,
"empirical_basis": avg_score,
"theoretical_framework": avg_score,
"impact": avg_score
}
total_score = sum(scores.values())
quality_grade = self.calculate_quality_grade(total_score)
# 生成简化版报告
report_content = f"""---
created: {datetime.now().strftime('%Y-%m-%d')}
title: 论文质量评估-{entry['id']}-{entry.get('year', '')}
tags: [质量评估, {quality_grade}, 批评估]
source: {entry.get('source', '')}
category: quality_assessment
---
# 论文质量评估报告(简化版)
## 文献基本信息
| 字段 | 内容 |
|------|------|
| **文献ID** | {entry['id']} |
| **标题** | {entry['title']} |
| **作者** | {entry['authors']} |
| **来源** | {entry.get('source', '')} |
| **年份** | {entry.get('year', '')} |
| **评估日期** | {datetime.now().strftime('%Y-%m-%d')} |
---
## 质量评估得分
| 评估维度 | 满分 | 得分 | 说明 |
|---------|------|------|------|
| 时效性 | 15 | {timeliness_score} | 发表年份:{year} |
| 信源权威性 | 20 | {source_authority_score} | 来源:{entry.get('source', '')} |
| 数据质量 | 20 | {avg_score} | 简化评估 |
| 方法严谨性 | 20 | {avg_score} | 简化评估 |
| 实证基础 | 20 | {avg_score} | 简化评估 |
| 理论框架 | 15 | {avg_score} | 简化评估 |
| 影响力 | 15 | {avg_score} | 简化评估 |
| **总分** | **105** | **{total_score}** | **质量等级:{quality_grade}** |
---
## 简化评估说明
此报告为批量评估的简化版本,数据质量、方法严谨性、实证基础、理论框架、影响力五个维度采用相同的平均分评估。如需详细评估,请运行单篇评估模式。
---
**质量等级:{quality_grade}**
**总分:{total_score}/105**
"""
# 保存报告
output_filename = f"论文质量评估-{entry['id']}-{datetime.now().strftime('%Y%m%d')}.md"
output_path = OUTPUT_DIR / output_filename
with open(output_path, "w", encoding="utf-8") as f:
f.write(report_content)
print(f"\n✅ 评估报告已生成:{output_path}")
print(f"✅ 总分:{total_score}/105,质量等级:{quality_grade}")
print(f"\n{'='*60}")
print("✅ 批量评估完成!")
print(f"{'='*60}")
def main():
"""主函数"""
parser = argparse.ArgumentParser(
description="文献质量评估报告生成器",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
使用示例:
python 质量评估报告生成器.py # 交互式单篇评估
python 质量评估报告生成器.py --batch # 批量评估(从文献库JSON读取)
python 质量评估报告生成器.py --help # 查看帮助
"""
)
parser.add_argument(
"--batch",
action="store_true",
help="批量评估模式(从文献库JSON读取)"
)
args = parser.parse_args()
# 创建评估器实例
assessor = QualityAssessment()
if args.batch:
# 批量评估模式
assessor.generate_batch_assessments()
else:
# 交互式单篇评估模式
assessor.generate_single_assessment()
if __name__ == "__main__":
main()