Files
llm_wiki/raw/教育AI研究/tools/质量评估报告生成器.py
hehaiguang1123 a6f05ab2d5 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
2026-07-01 08:05:43 +08:00

612 lines
20 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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()