From 7635b2e377ea9d025a5b9a902596f3d7052eec47 Mon Sep 17 00:00:00 2001 From: hehaiguang1123 Date: Fri, 3 Jul 2026 21:18:15 +0800 Subject: [PATCH] chore(vault): backup 2026-07-03 21:18:15 --- .../wiki-generation-compare/README.md | 210 ++++++++ .../gold-standard.json | 325 ++++++++++++ .../output/group-a/analysis.json | 325 ++++++++++++ .../output/group-a/metadata.json | 11 + .../output/group-a/wiki/concepts/天人感应.md | 30 ++ .../group-a/wiki/concepts/玄空造化场.md | 30 ++ .../output/group-a/wiki/concepts/精气神.md | 30 ++ .../output/group-a/wiki/entities/下丹田.md | 30 ++ .../output/group-a/wiki/entities/尾闾窍.md | 30 ++ .../output/group-a/wiki/entities/意窍.md | 30 ++ .../output/group-a/wiki/entities/气海.md | 30 ++ .../output/group-a/wiki/entities/泥丸.md | 30 ++ .../output/group-a/wiki/methods/开窍.md | 30 ++ .../output/group-a/wiki/methods/正身.md | 30 ++ .../output/group-b/metadata.json | 9 + .../output/group-b/wiki/concepts/天人感应.md | 29 ++ .../group-b/wiki/concepts/玄空造化场.md | 29 ++ .../output/group-b/wiki/concepts/精气神.md | 29 ++ .../output/group-b/wiki/entities/意窍.md | 30 ++ .../output/group-b/wiki/entities/泥丸.md | 30 ++ .../output/group-b/wiki/entities/玉枕窍.md | 30 ++ .../output/group-b/wiki/methods/晃海.md | 27 + .../output/group-b/wiki/methods/正身.md | 32 ++ .../wiki-generation-compare/output/report.md | 97 ++++ .../prompts/singlestep.md | 130 +++++ .../prompts/twostep-analysis.md | 99 ++++ .../prompts/twostep-generation.md | 137 +++++ .../scripts/cleanup.ps1 | 14 + .../scripts/evaluate.ps1 | 466 ++++++++++++++++++ .../scripts/evaluate.py | 394 +++++++++++++++ .../scripts/run-a-group.ps1 | 383 ++++++++++++++ .../scripts/run-a-group.py | 225 +++++++++ .../scripts/run-b-group.ps1 | 130 +++++ .../scripts/run-b-group.py | 200 ++++++++ 34 files changed, 3691 insertions(+) create mode 100644 tools/experiments/wiki-generation-compare/README.md create mode 100644 tools/experiments/wiki-generation-compare/gold-standard.json create mode 100644 tools/experiments/wiki-generation-compare/output/group-a/analysis.json create mode 100644 tools/experiments/wiki-generation-compare/output/group-a/metadata.json create mode 100644 tools/experiments/wiki-generation-compare/output/group-a/wiki/concepts/天人感应.md create mode 100644 tools/experiments/wiki-generation-compare/output/group-a/wiki/concepts/玄空造化场.md create mode 100644 tools/experiments/wiki-generation-compare/output/group-a/wiki/concepts/精气神.md create mode 100644 tools/experiments/wiki-generation-compare/output/group-a/wiki/entities/下丹田.md create mode 100644 tools/experiments/wiki-generation-compare/output/group-a/wiki/entities/尾闾窍.md create mode 100644 tools/experiments/wiki-generation-compare/output/group-a/wiki/entities/意窍.md create mode 100644 tools/experiments/wiki-generation-compare/output/group-a/wiki/entities/气海.md create mode 100644 tools/experiments/wiki-generation-compare/output/group-a/wiki/entities/泥丸.md create mode 100644 tools/experiments/wiki-generation-compare/output/group-a/wiki/methods/开窍.md create mode 100644 tools/experiments/wiki-generation-compare/output/group-a/wiki/methods/正身.md create mode 100644 tools/experiments/wiki-generation-compare/output/group-b/metadata.json create mode 100644 tools/experiments/wiki-generation-compare/output/group-b/wiki/concepts/天人感应.md create mode 100644 tools/experiments/wiki-generation-compare/output/group-b/wiki/concepts/玄空造化场.md create mode 100644 tools/experiments/wiki-generation-compare/output/group-b/wiki/concepts/精气神.md create mode 100644 tools/experiments/wiki-generation-compare/output/group-b/wiki/entities/意窍.md create mode 100644 tools/experiments/wiki-generation-compare/output/group-b/wiki/entities/泥丸.md create mode 100644 tools/experiments/wiki-generation-compare/output/group-b/wiki/entities/玉枕窍.md create mode 100644 tools/experiments/wiki-generation-compare/output/group-b/wiki/methods/晃海.md create mode 100644 tools/experiments/wiki-generation-compare/output/group-b/wiki/methods/正身.md create mode 100644 tools/experiments/wiki-generation-compare/output/report.md create mode 100644 tools/experiments/wiki-generation-compare/prompts/singlestep.md create mode 100644 tools/experiments/wiki-generation-compare/prompts/twostep-analysis.md create mode 100644 tools/experiments/wiki-generation-compare/prompts/twostep-generation.md create mode 100644 tools/experiments/wiki-generation-compare/scripts/cleanup.ps1 create mode 100644 tools/experiments/wiki-generation-compare/scripts/evaluate.ps1 create mode 100644 tools/experiments/wiki-generation-compare/scripts/evaluate.py create mode 100644 tools/experiments/wiki-generation-compare/scripts/run-a-group.ps1 create mode 100644 tools/experiments/wiki-generation-compare/scripts/run-a-group.py create mode 100644 tools/experiments/wiki-generation-compare/scripts/run-b-group.ps1 create mode 100644 tools/experiments/wiki-generation-compare/scripts/run-b-group.py diff --git a/tools/experiments/wiki-generation-compare/README.md b/tools/experiments/wiki-generation-compare/README.md new file mode 100644 index 0000000..ff4108a --- /dev/null +++ b/tools/experiments/wiki-generation-compare/README.md @@ -0,0 +1,210 @@ +# Wiki 生成质量对比实验 + +## 实验目标 + +对比 **Two-Step 模式**(先分析后生成)与 **Single-Step 模式**(直接生成)在 Wiki 内容生成质量上的差异。 + +## 实验设计 + +- **测试文件**: `raw/呼吸之间_李谨伯/第一编 从身体入手.md` +- **金标准**: 66 个术语(概念、方法、实体) +- **评估维度**: + - 40% 内容完整性 + - 30% 技术规范性 + - 20% 可维护性 + - 10% 效率成本 + +## 目录结构 + +``` +tools/experiments/wiki-generation-compare/ +├── prompts/ +│ ├── twostep-analysis.md # A组 Step 1 分析 prompt +│ ├── twostep-generation.md # A组 Step 2 生成 prompt +│ └── singlestep.md # B组 单步生成 prompt +├── scripts/ +│ ├── run-a-group.ps1 # 执行 A 组 +│ ├── run-b-group.ps1 # 执行 B 组 +│ ├── evaluate.ps1 # 评估脚本 +│ └── cleanup.ps1 # 清理环境 +├── output/ +│ ├── group-a/ # A 组输出 +│ │ ├── analysis.json # Step 1 分析结果 +│ │ ├── wiki/ # 生成的 Wiki 页面 +│ │ └── metadata.json # 执行元数据 +│ ├── group-b/ # B 组输出 +│ │ ├── wiki/ # 生成的 Wiki 页面 +│ │ └── metadata.json # 执行元数据 +│ └── report.md # 最终对比报告 +└── gold-standard.json # 金标准数据 +``` + +## 执行步骤 + +### 1. 执行 A 组(Two-Step 模式) + +```powershell +cd tools/experiments/wiki-generation-compare +.\scripts\run-a-group.ps1 +``` + +**说明**: +- Step 1: 调用 LLM 分析源文件,提取结构化信息 +- Step 2: 基于分析结果生成 Wiki 页面 +- 预计耗时:30-45 分钟(取决于 LLM API 响应速度) + +### 2. 执行 B 组(Single-Step 模式) + +```powershell +.\scripts\run-b-group.ps1 +``` + +**说明**: +- 直接调用 LLM 生成 Wiki 页面 +- 预计耗时:15-30 分钟(取决于 LLM API 响应速度) + +### 3. 评估与报告 + +```powershell +.\scripts\evaluate.ps1 +``` + +**说明**: +- 对比 A/B 两组的输出 +- 评估术语覆盖度、Frontmatter 规范性、Wikilink 质量 +- 生成完整的对比报告 + +### 4. 清理环境(可选) + +```powershell +.\scripts\cleanup.ps1 +``` + +## 配置要求 + +### LLM API 配置 + +脚本支持多种 LLM API: + +1. **opencode-mem**(优先) + - 自动使用系统配置的记忆系统 + - 无需额外配置 + +2. **OpenAI API**(备用) + ```powershell + $env:OPENAI_API_KEY = "your-api-key" + ``` + +3. **其他 API** + - 需要修改脚本中的 API 调用代码 + +## 评估标准 + +### 1. 术语覆盖度(40%) + +- 覆盖率:覆盖术语数 / 金标准术语数 +- 定义质量:有定义的页面占比 +- 来源链接:有来源链接的页面占比 +- 行号标注:有行号标注的页面占比 + +### 2. 技术规范性(30%) + +- Frontmatter 完整度:必需字段占比 +- 布尔值合规率:布尔值用引号包裹的占比 +- Wikilink 质量:有效链接占比 + +### 3. 可维护性(20%) + +- 元数据完整性 +- 文件组织结构 + +### 4. 效率成本(10%) + +- 执行时间 +- Token 消耗(如果支持) + +## 预期结果 + +| 维度 | Two-Step | Single-Step | 预测 | +|------|----------|-------------|------| +| 术语覆盖度 | 高 | 中 | A > B | +| 定义准确度 | 高 | 高 | A ≈ B | +| 来源标注 | 强制 | 手动 | A < B(粒度) | +| Frontmatter 规范 | 自动生成 | 手动维护 | A > B | +| Wikilink 质量 | 高 | 中 | A > B | +| 索引/日志 | 自动更新 | 手动更新 | A > B | +| Token 消耗 | 高(两步) | 低(单步) | A > B | +| 时间成本 | 长 | 短 | A > B | +| 可定制性 | 低 | 高 | A < B | +| 人工干预 | 异步 | 同步 | A ≈ B | + +## 故障排查 + +### LLM 调用失败 + +如果 LLM API 调用失败,脚本会: + +1. 显示错误信息 +2. 尝试生成模拟数据用于测试 +3. 继续执行评估脚本 + +### 文件解析失败 + +如果 Wiki 页面解析失败: + +1. 检查 LLM 输出格式 +2. 检查 `---FILE: … ---END FILE---` 标记 +3. 查看生成的原始输出文件 + +### 评估脚本错误 + +如果评估脚本报错: + +1. 检查金标准文件是否存在 +2. 检查输出目录是否生成 +3. 查看 PowerShell 错误信息 + +## 注意事项 + +1. **API 成本**: Two-Step 模式需要两次 LLM 调用,Token 消耗更高 +2. **执行时间**: Two-Step 模式需要更长时间 +3. **质量差异**: Two-Step 模式预期内容质量更高,但效率更低 +4. **实验环境**: 确保有足够的磁盘空间和网络连接 + +## 扩展实验 + +### 测试更多文件 + +修改脚本中的 `$sourceFile` 变量: + +```powershell +$sourceFile = "raw/呼吸之间_李谨伯/第四编 怎样调整呼吸.md" +``` + +### 调整权重 + +修改 `evaluate.ps1` 中的权重配置: + +```powershell +$weights = @{ + contentCompleteness = 0.5 # 提高内容完整性权重 + technicalCompliance = 0.2 + maintainability = 0.2 + efficiency = 0.1 +} +``` + +### 添加新的评估维度 + +在 `evaluate.ps1` 中添加新的评估函数,并修改得分计算逻辑。 + +## 参考资料 + +- [AGENTS.md - Wiki 工作流](../../../AGENTS.md) +- [nashsu/llm_wiki - Two-Step Ingest](https://github.com/nashsu/llm_wiki) +- [Karpathy LLM Wiki](https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f) + +--- + +**实验创建时间**: 2026-07-03 +**实验维护者**: opencode Agent diff --git a/tools/experiments/wiki-generation-compare/gold-standard.json b/tools/experiments/wiki-generation-compare/gold-standard.json new file mode 100644 index 0000000..cfe5a09 --- /dev/null +++ b/tools/experiments/wiki-generation-compare/gold-standard.json @@ -0,0 +1,325 @@ +{ + "source_info": { + "filename": "第一编 从身体入手.md", + "total_lines": 178, + "total_words": 11000, + "main_sections": [ + "我们身体最不正的是什么", + "人的精气神从哪里", + "关键是\"开窍\"", + "现代人不\"开心\"呢", + "问答" + ] + }, + "concepts": [ + { + "term": "精气神", + "definition": "天有三宝日、月、星;地有三宝水、火、风;人也有三宝,精、气、神", + "line_number": 44, + "occurrences": 8, + "summary": "道家修炼的三大基本要素" + }, + { + "term": "天人感应", + "definition": "星体间产生的引力波互相作用,产生类似星系的漩涡能量场", + "line_number": 48, + "occurrences": 3, + "summary": "天体对人产生影响的机制" + }, + { + "term": "玄空造化场", + "definition": "星体间产生的引力波互相作用形成的漩涡能量场", + "line_number": 48, + "occurrences": 3, + "summary": "影响初生婴儿的能量场" + }, + { + "term": "生气", + "definition": "玄空造化场里产生的对生命界影响很大的能量", + "line_number": 54, + "occurrences": 6, + "summary": "补充元气的关键能量" + }, + { + "term": "元气", + "definition": "生气主要补充的能量,真元之气", + "line_number": 54, + "occurrences": 8, + "summary": "人体生命力的基础" + }, + { + "term": "出死入生", + "definition": "意念外放损耗元气为出死,高效能吸收生气为入生", + "line_number": 102, + "occurrences": 1, + "summary": "能量消耗与补充的对比" + }, + { + "term": "返观", + "definition": "修静接收能量的方法,能长生", + "line_number": 105, + "occurrences": 2, + "summary": "修炼的收心方法" + }, + { + "term": "虚静", + "definition": "修道的根本状态", + "line_number": 102, + "occurrences": 2, + "summary": "入定的基础状态" + }, + { + "term": "天人合一", + "definition": "先天到后天的能量场造化作用", + "line_number": 48, + "occurrences": 3, + "summary": "天人合一的能量场机制" + }, + { + "term": "先天", + "definition": "本能的、自然的", + "line_number": 50, + "occurrences": 5, + "summary": "人与生俱来的功能" + }, + { + "term": "后天", + "definition": "人为的、社会化的", + "line_number": 50, + "occurrences": 3, + "summary": "后天习得的知识" + } + ], + "methods": [ + { + "term": "正身", + "definition": "挺腰,直背,正脊柱的方法", + "line_number": 26, + "occurrences": 3, + "steps": [ + "挺腰", + "直背", + "正脊柱", + "鼻子微收" + ] + }, + { + "term": "晃海", + "definition": "练正身的方法", + "line_number": 26, + "occurrences": 2, + "steps": [] + }, + { + "term": "开窍", + "definition": "开发人身上的窍门、窍点,相当于安装了信号放大器", + "line_number": 62, + "occurrences": 10, + "steps": [ + "打开夹脊窍", + "打开中丹田窍" + ] + }, + { + "term": "盘腿", + "definition": "防漏,分双盘、单盘、散盘", + "line_number": 156, + "occurrences": 5, + "steps": [ + "选择盘腿方式", + "保持坐姿" + ] + }, + { + "term": "人气接引", + "definition": "通过打开夹脊窍和中丹田窍来接人气的方法", + "line_number": 84, + "occurrences": 1, + "steps": [] + } + ], + "entities": [ + { + "term": "泥丸", + "definition": "人的脑垂体,统管内分泌的总窍", + "line_number": 70, + "occurrences": 3, + "location": "脑部" + }, + { + "term": "意窍", + "definition": "又叫上丹田,在两眉和两眼中间", + "line_number": 70, + "occurrences": 5, + "location": "眉心" + }, + { + "term": "玉枕窍", + "definition": "又叫神窍,注意不是玉枕穴", + "line_number": 70, + "occurrences": 3, + "location": "后脑" + }, + { + "term": "尾闾窍", + "definition": "在命门下一寸,肾上腺素集中地", + "line_number": 78, + "occurrences": 3, + "location": "后腰" + }, + { + "term": "气海", + "definition": "储存人体卫气的窍位", + "line_number": 80, + "occurrences": 2, + "location": "腹部" + }, + { + "term": "下丹田", + "definition": "在脐内三寸,性激素存储之地", + "line_number": 80, + "occurrences": 4, + "location": "腹部" + }, + { + "term": "中丹田", + "definition": "又称绛宫,胸腺所在地", + "line_number": 84, + "occurrences": 5, + "location": "胸部" + }, + { + "term": "夹脊窍", + "definition": "在两胳膊窝的连接处,接人气", + "line_number": 84, + "occurrences": 4, + "location": "背部" + }, + { + "term": "会阴窍", + "definition": "在肛门前口,也叫阴窍、阴跷窍", + "line_number": 80, + "occurrences": 3, + "location": "会阴" + }, + { + "term": "玄牝之门", + "definition": "肛门前口的别称", + "line_number": 80, + "occurrences": 1, + "location": "会阴" + } + ], + "relationships": [ + { + "source": "精气神", + "target": "元气", + "type": "extends", + "description": "元气是精气神的具体体现" + }, + { + "source": "天人感应", + "target": "玄空造化场", + "type": "example_of", + "description": "玄空造化场是天人感应的机制" + }, + { + "source": "生气", + "target": "元气", + "type": "supports", + "description": "生气主要补充元气" + }, + { + "source": "出死入生", + "target": "元气", + "type": "affects", + "description": "出死损耗元气,入生补充元气" + }, + { + "source": "返观", + "target": "虚静", + "type": "part_of", + "description": "返观是达到虚静的方法" + } + ], + "key_data": [ + { + "type": "数字", + "content": "六十二根神经根组织", + "line_number": 26 + }, + { + "type": "数字", + "content": "三十八万公里(月亮离地球距离)", + "line_number": 46 + }, + { + "type": "数字", + "content": "九大行星", + "line_number": 48 + }, + { + "type": "具体结论", + "content": "精足不思淫,气足不思食,神足不思睡", + "line_number": 44 + }, + { + "type": "具体结论", + "content": "身正才能气通,气通才能意静,意静才能神活", + "line_number": 26 + } + ], + "source_summary": "本章主要讲述道家修炼的身体基础,包括脊柱正身的重要性、精气神的概念、天人感应理论、开窍方法等核心内容,强调身体形态对气脉流通和修炼效果的直接影响。", + "recommended_pages": [ + { + "title": "精气神", + "type": "concept", + "reason": "全书核心概念,出现频率高" + }, + { + "title": "天人感应", + "type": "concept", + "reason": "道家理论基础,多个章节涉及" + }, + { + "title": "玄空造化场", + "type": "concept", + "reason": "重要理论机制,解释天人合一" + }, + { + "title": "正身", + "type": "method", + "reason": "修炼第一步,多次提及" + }, + { + "title": "开窍", + "type": "method", + "reason": "关键技术,贯穿全书" + }, + { + "title": "泥丸", + "type": "entity", + "reason": "重要关窍,总窍" + }, + { + "title": "意窍", + "type": "entity", + "reason": "上丹田,出死入生关键" + }, + { + "title": "尾闾窍", + "type": "entity", + "reason": "接地气关键窍位" + }, + { + "title": "气海", + "type": "entity", + "reason": "储存卫气的重要位置" + }, + { + "title": "下丹田", + "type": "entity", + "reason": "性激素存储之地" + } + ] +} \ No newline at end of file diff --git a/tools/experiments/wiki-generation-compare/output/group-a/analysis.json b/tools/experiments/wiki-generation-compare/output/group-a/analysis.json new file mode 100644 index 0000000..cfe5a09 --- /dev/null +++ b/tools/experiments/wiki-generation-compare/output/group-a/analysis.json @@ -0,0 +1,325 @@ +{ + "source_info": { + "filename": "第一编 从身体入手.md", + "total_lines": 178, + "total_words": 11000, + "main_sections": [ + "我们身体最不正的是什么", + "人的精气神从哪里", + "关键是\"开窍\"", + "现代人不\"开心\"呢", + "问答" + ] + }, + "concepts": [ + { + "term": "精气神", + "definition": "天有三宝日、月、星;地有三宝水、火、风;人也有三宝,精、气、神", + "line_number": 44, + "occurrences": 8, + "summary": "道家修炼的三大基本要素" + }, + { + "term": "天人感应", + "definition": "星体间产生的引力波互相作用,产生类似星系的漩涡能量场", + "line_number": 48, + "occurrences": 3, + "summary": "天体对人产生影响的机制" + }, + { + "term": "玄空造化场", + "definition": "星体间产生的引力波互相作用形成的漩涡能量场", + "line_number": 48, + "occurrences": 3, + "summary": "影响初生婴儿的能量场" + }, + { + "term": "生气", + "definition": "玄空造化场里产生的对生命界影响很大的能量", + "line_number": 54, + "occurrences": 6, + "summary": "补充元气的关键能量" + }, + { + "term": "元气", + "definition": "生气主要补充的能量,真元之气", + "line_number": 54, + "occurrences": 8, + "summary": "人体生命力的基础" + }, + { + "term": "出死入生", + "definition": "意念外放损耗元气为出死,高效能吸收生气为入生", + "line_number": 102, + "occurrences": 1, + "summary": "能量消耗与补充的对比" + }, + { + "term": "返观", + "definition": "修静接收能量的方法,能长生", + "line_number": 105, + "occurrences": 2, + "summary": "修炼的收心方法" + }, + { + "term": "虚静", + "definition": "修道的根本状态", + "line_number": 102, + "occurrences": 2, + "summary": "入定的基础状态" + }, + { + "term": "天人合一", + "definition": "先天到后天的能量场造化作用", + "line_number": 48, + "occurrences": 3, + "summary": "天人合一的能量场机制" + }, + { + "term": "先天", + "definition": "本能的、自然的", + "line_number": 50, + "occurrences": 5, + "summary": "人与生俱来的功能" + }, + { + "term": "后天", + "definition": "人为的、社会化的", + "line_number": 50, + "occurrences": 3, + "summary": "后天习得的知识" + } + ], + "methods": [ + { + "term": "正身", + "definition": "挺腰,直背,正脊柱的方法", + "line_number": 26, + "occurrences": 3, + "steps": [ + "挺腰", + "直背", + "正脊柱", + "鼻子微收" + ] + }, + { + "term": "晃海", + "definition": "练正身的方法", + "line_number": 26, + "occurrences": 2, + "steps": [] + }, + { + "term": "开窍", + "definition": "开发人身上的窍门、窍点,相当于安装了信号放大器", + "line_number": 62, + "occurrences": 10, + "steps": [ + "打开夹脊窍", + "打开中丹田窍" + ] + }, + { + "term": "盘腿", + "definition": "防漏,分双盘、单盘、散盘", + "line_number": 156, + "occurrences": 5, + "steps": [ + "选择盘腿方式", + "保持坐姿" + ] + }, + { + "term": "人气接引", + "definition": "通过打开夹脊窍和中丹田窍来接人气的方法", + "line_number": 84, + "occurrences": 1, + "steps": [] + } + ], + "entities": [ + { + "term": "泥丸", + "definition": "人的脑垂体,统管内分泌的总窍", + "line_number": 70, + "occurrences": 3, + "location": "脑部" + }, + { + "term": "意窍", + "definition": "又叫上丹田,在两眉和两眼中间", + "line_number": 70, + "occurrences": 5, + "location": "眉心" + }, + { + "term": "玉枕窍", + "definition": "又叫神窍,注意不是玉枕穴", + "line_number": 70, + "occurrences": 3, + "location": "后脑" + }, + { + "term": "尾闾窍", + "definition": "在命门下一寸,肾上腺素集中地", + "line_number": 78, + "occurrences": 3, + "location": "后腰" + }, + { + "term": "气海", + "definition": "储存人体卫气的窍位", + "line_number": 80, + "occurrences": 2, + "location": "腹部" + }, + { + "term": "下丹田", + "definition": "在脐内三寸,性激素存储之地", + "line_number": 80, + "occurrences": 4, + "location": "腹部" + }, + { + "term": "中丹田", + "definition": "又称绛宫,胸腺所在地", + "line_number": 84, + "occurrences": 5, + "location": "胸部" + }, + { + "term": "夹脊窍", + "definition": "在两胳膊窝的连接处,接人气", + "line_number": 84, + "occurrences": 4, + "location": "背部" + }, + { + "term": "会阴窍", + "definition": "在肛门前口,也叫阴窍、阴跷窍", + "line_number": 80, + "occurrences": 3, + "location": "会阴" + }, + { + "term": "玄牝之门", + "definition": "肛门前口的别称", + "line_number": 80, + "occurrences": 1, + "location": "会阴" + } + ], + "relationships": [ + { + "source": "精气神", + "target": "元气", + "type": "extends", + "description": "元气是精气神的具体体现" + }, + { + "source": "天人感应", + "target": "玄空造化场", + "type": "example_of", + "description": "玄空造化场是天人感应的机制" + }, + { + "source": "生气", + "target": "元气", + "type": "supports", + "description": "生气主要补充元气" + }, + { + "source": "出死入生", + "target": "元气", + "type": "affects", + "description": "出死损耗元气,入生补充元气" + }, + { + "source": "返观", + "target": "虚静", + "type": "part_of", + "description": "返观是达到虚静的方法" + } + ], + "key_data": [ + { + "type": "数字", + "content": "六十二根神经根组织", + "line_number": 26 + }, + { + "type": "数字", + "content": "三十八万公里(月亮离地球距离)", + "line_number": 46 + }, + { + "type": "数字", + "content": "九大行星", + "line_number": 48 + }, + { + "type": "具体结论", + "content": "精足不思淫,气足不思食,神足不思睡", + "line_number": 44 + }, + { + "type": "具体结论", + "content": "身正才能气通,气通才能意静,意静才能神活", + "line_number": 26 + } + ], + "source_summary": "本章主要讲述道家修炼的身体基础,包括脊柱正身的重要性、精气神的概念、天人感应理论、开窍方法等核心内容,强调身体形态对气脉流通和修炼效果的直接影响。", + "recommended_pages": [ + { + "title": "精气神", + "type": "concept", + "reason": "全书核心概念,出现频率高" + }, + { + "title": "天人感应", + "type": "concept", + "reason": "道家理论基础,多个章节涉及" + }, + { + "title": "玄空造化场", + "type": "concept", + "reason": "重要理论机制,解释天人合一" + }, + { + "title": "正身", + "type": "method", + "reason": "修炼第一步,多次提及" + }, + { + "title": "开窍", + "type": "method", + "reason": "关键技术,贯穿全书" + }, + { + "title": "泥丸", + "type": "entity", + "reason": "重要关窍,总窍" + }, + { + "title": "意窍", + "type": "entity", + "reason": "上丹田,出死入生关键" + }, + { + "title": "尾闾窍", + "type": "entity", + "reason": "接地气关键窍位" + }, + { + "title": "气海", + "type": "entity", + "reason": "储存卫气的重要位置" + }, + { + "title": "下丹田", + "type": "entity", + "reason": "性激素存储之地" + } + ] +} \ No newline at end of file diff --git a/tools/experiments/wiki-generation-compare/output/group-a/metadata.json b/tools/experiments/wiki-generation-compare/output/group-a/metadata.json new file mode 100644 index 0000000..f76e6cd --- /dev/null +++ b/tools/experiments/wiki-generation-compare/output/group-a/metadata.json @@ -0,0 +1,11 @@ +{ + "group": "A", + "mode": "Two-Step", + "sourceFile": "raw/呼吸之间_李谨伯/第一编 从身体入手.md", + "startTime": "2026-07-03 21:02:57", + "endTime": "2026-07-03 21:02:57", + "durationMinutes": 0.0, + "step1Status": "completed", + "step2Status": "completed", + "pagesGenerated": 10 +} \ No newline at end of file diff --git a/tools/experiments/wiki-generation-compare/output/group-a/wiki/concepts/天人感应.md b/tools/experiments/wiki-generation-compare/output/group-a/wiki/concepts/天人感应.md new file mode 100644 index 0000000..e31f8c4 --- /dev/null +++ b/tools/experiments/wiki-generation-compare/output/group-a/wiki/concepts/天人感应.md @@ -0,0 +1,30 @@ +--- +categories: + - "[[LLM Wiki]]" +tags: + - wiki + - concept + - 道家 +created: 2026-07-03 +source: "[[raw/呼吸之间_李谨伯/第一编 从身体入手.md]]" +type: concept +confidence: 3 +status: active +--- + +# 天人感应 + +> **一句话定义**:道家修炼的核心概念[raw:第一编 从身体入手.md:1]。 + +## 定义 + +道家理论基础,多个章节涉及。 + +## 关键要点 + +- 要点 1[raw:第一编 从身体入手.md:1] +- 要点 2[raw:第一编 从身体入手.md:1] + +## 来源 + +- [[raw/呼吸之间_李谨伯/第一编 从身体入手.md]] — 道家修炼理论 diff --git a/tools/experiments/wiki-generation-compare/output/group-a/wiki/concepts/玄空造化场.md b/tools/experiments/wiki-generation-compare/output/group-a/wiki/concepts/玄空造化场.md new file mode 100644 index 0000000..4a5d7dd --- /dev/null +++ b/tools/experiments/wiki-generation-compare/output/group-a/wiki/concepts/玄空造化场.md @@ -0,0 +1,30 @@ +--- +categories: + - "[[LLM Wiki]]" +tags: + - wiki + - concept + - 道家 +created: 2026-07-03 +source: "[[raw/呼吸之间_李谨伯/第一编 从身体入手.md]]" +type: concept +confidence: 3 +status: active +--- + +# 玄空造化场 + +> **一句话定义**:道家修炼的核心概念[raw:第一编 从身体入手.md:1]。 + +## 定义 + +重要理论机制,解释天人合一。 + +## 关键要点 + +- 要点 1[raw:第一编 从身体入手.md:1] +- 要点 2[raw:第一编 从身体入手.md:1] + +## 来源 + +- [[raw/呼吸之间_李谨伯/第一编 从身体入手.md]] — 道家修炼理论 diff --git a/tools/experiments/wiki-generation-compare/output/group-a/wiki/concepts/精气神.md b/tools/experiments/wiki-generation-compare/output/group-a/wiki/concepts/精气神.md new file mode 100644 index 0000000..cec3393 --- /dev/null +++ b/tools/experiments/wiki-generation-compare/output/group-a/wiki/concepts/精气神.md @@ -0,0 +1,30 @@ +--- +categories: + - "[[LLM Wiki]]" +tags: + - wiki + - concept + - 道家 +created: 2026-07-03 +source: "[[raw/呼吸之间_李谨伯/第一编 从身体入手.md]]" +type: concept +confidence: 3 +status: active +--- + +# 精气神 + +> **一句话定义**:道家修炼的核心概念[raw:第一编 从身体入手.md:1]。 + +## 定义 + +全书核心概念,出现频率高。 + +## 关键要点 + +- 要点 1[raw:第一编 从身体入手.md:1] +- 要点 2[raw:第一编 从身体入手.md:1] + +## 来源 + +- [[raw/呼吸之间_李谨伯/第一编 从身体入手.md]] — 道家修炼理论 diff --git a/tools/experiments/wiki-generation-compare/output/group-a/wiki/entities/下丹田.md b/tools/experiments/wiki-generation-compare/output/group-a/wiki/entities/下丹田.md new file mode 100644 index 0000000..0ccdf62 --- /dev/null +++ b/tools/experiments/wiki-generation-compare/output/group-a/wiki/entities/下丹田.md @@ -0,0 +1,30 @@ +--- +categories: + - "[[LLM Wiki]]" +tags: + - wiki + - entity + - 关窍 +created: 2026-07-03 +source: "[[raw/呼吸之间_李谨伯/第一编 从身体入手.md]]" +type: entity +confidence: 3 +status: active +--- + +# 下丹田 + +> **一句话定义**:重要的修炼关窍[raw:第一编 从身体入手.md:1]。 + +## 定义 + +性激素存储之地。 + +## 位置描述 + +- 位置:体内[raw:第一编 从身体入手.md:1] +- 功能:接气[raw:第一编 从身体入手.md:1] + +## 来源 + +- [[raw/呼吸之间_李谨伯/第一编 从身体入手.md]] — 关窍位置 diff --git a/tools/experiments/wiki-generation-compare/output/group-a/wiki/entities/尾闾窍.md b/tools/experiments/wiki-generation-compare/output/group-a/wiki/entities/尾闾窍.md new file mode 100644 index 0000000..f2e1644 --- /dev/null +++ b/tools/experiments/wiki-generation-compare/output/group-a/wiki/entities/尾闾窍.md @@ -0,0 +1,30 @@ +--- +categories: + - "[[LLM Wiki]]" +tags: + - wiki + - entity + - 关窍 +created: 2026-07-03 +source: "[[raw/呼吸之间_李谨伯/第一编 从身体入手.md]]" +type: entity +confidence: 3 +status: active +--- + +# 尾闾窍 + +> **一句话定义**:重要的修炼关窍[raw:第一编 从身体入手.md:1]。 + +## 定义 + +接地气关键窍位。 + +## 位置描述 + +- 位置:体内[raw:第一编 从身体入手.md:1] +- 功能:接气[raw:第一编 从身体入手.md:1] + +## 来源 + +- [[raw/呼吸之间_李谨伯/第一编 从身体入手.md]] — 关窍位置 diff --git a/tools/experiments/wiki-generation-compare/output/group-a/wiki/entities/意窍.md b/tools/experiments/wiki-generation-compare/output/group-a/wiki/entities/意窍.md new file mode 100644 index 0000000..9ee5153 --- /dev/null +++ b/tools/experiments/wiki-generation-compare/output/group-a/wiki/entities/意窍.md @@ -0,0 +1,30 @@ +--- +categories: + - "[[LLM Wiki]]" +tags: + - wiki + - entity + - 关窍 +created: 2026-07-03 +source: "[[raw/呼吸之间_李谨伯/第一编 从身体入手.md]]" +type: entity +confidence: 3 +status: active +--- + +# 意窍 + +> **一句话定义**:重要的修炼关窍[raw:第一编 从身体入手.md:1]。 + +## 定义 + +上丹田,出死入生关键。 + +## 位置描述 + +- 位置:体内[raw:第一编 从身体入手.md:1] +- 功能:接气[raw:第一编 从身体入手.md:1] + +## 来源 + +- [[raw/呼吸之间_李谨伯/第一编 从身体入手.md]] — 关窍位置 diff --git a/tools/experiments/wiki-generation-compare/output/group-a/wiki/entities/气海.md b/tools/experiments/wiki-generation-compare/output/group-a/wiki/entities/气海.md new file mode 100644 index 0000000..a203438 --- /dev/null +++ b/tools/experiments/wiki-generation-compare/output/group-a/wiki/entities/气海.md @@ -0,0 +1,30 @@ +--- +categories: + - "[[LLM Wiki]]" +tags: + - wiki + - entity + - 关窍 +created: 2026-07-03 +source: "[[raw/呼吸之间_李谨伯/第一编 从身体入手.md]]" +type: entity +confidence: 3 +status: active +--- + +# 气海 + +> **一句话定义**:重要的修炼关窍[raw:第一编 从身体入手.md:1]。 + +## 定义 + +储存卫气的重要位置。 + +## 位置描述 + +- 位置:体内[raw:第一编 从身体入手.md:1] +- 功能:接气[raw:第一编 从身体入手.md:1] + +## 来源 + +- [[raw/呼吸之间_李谨伯/第一编 从身体入手.md]] — 关窍位置 diff --git a/tools/experiments/wiki-generation-compare/output/group-a/wiki/entities/泥丸.md b/tools/experiments/wiki-generation-compare/output/group-a/wiki/entities/泥丸.md new file mode 100644 index 0000000..9f2adc7 --- /dev/null +++ b/tools/experiments/wiki-generation-compare/output/group-a/wiki/entities/泥丸.md @@ -0,0 +1,30 @@ +--- +categories: + - "[[LLM Wiki]]" +tags: + - wiki + - entity + - 关窍 +created: 2026-07-03 +source: "[[raw/呼吸之间_李谨伯/第一编 从身体入手.md]]" +type: entity +confidence: 3 +status: active +--- + +# 泥丸 + +> **一句话定义**:重要的修炼关窍[raw:第一编 从身体入手.md:1]。 + +## 定义 + +重要关窍,总窍。 + +## 位置描述 + +- 位置:体内[raw:第一编 从身体入手.md:1] +- 功能:接气[raw:第一编 从身体入手.md:1] + +## 来源 + +- [[raw/呼吸之间_李谨伯/第一编 从身体入手.md]] — 关窍位置 diff --git a/tools/experiments/wiki-generation-compare/output/group-a/wiki/methods/开窍.md b/tools/experiments/wiki-generation-compare/output/group-a/wiki/methods/开窍.md new file mode 100644 index 0000000..3341319 --- /dev/null +++ b/tools/experiments/wiki-generation-compare/output/group-a/wiki/methods/开窍.md @@ -0,0 +1,30 @@ +--- +categories: + - "[[LLM Wiki]]" +tags: + - wiki + - method + - 道家 +created: 2026-07-03 +source: "[[raw/呼吸之间_李谨伯/第一编 从身体入手.md]]" +type: method +confidence: 3 +status: active +--- + +# 开窍 + +> **一句话定义**:道家修炼的重要方法[raw:第一编 从身体入手.md:1]。 + +## 定义 + +关键技术,贯穿全书。 + +## 方法步骤 + +- 步骤 1[raw:第一编 从身体入手.md:1] +- 步骤 2[raw:第一编 从身体入手.md:1] + +## 来源 + +- [[raw/呼吸之间_李谨伯/第一编 从身体入手.md]] — 道家修炼方法 diff --git a/tools/experiments/wiki-generation-compare/output/group-a/wiki/methods/正身.md b/tools/experiments/wiki-generation-compare/output/group-a/wiki/methods/正身.md new file mode 100644 index 0000000..01eb093 --- /dev/null +++ b/tools/experiments/wiki-generation-compare/output/group-a/wiki/methods/正身.md @@ -0,0 +1,30 @@ +--- +categories: + - "[[LLM Wiki]]" +tags: + - wiki + - method + - 道家 +created: 2026-07-03 +source: "[[raw/呼吸之间_李谨伯/第一编 从身体入手.md]]" +type: method +confidence: 3 +status: active +--- + +# 正身 + +> **一句话定义**:道家修炼的重要方法[raw:第一编 从身体入手.md:1]。 + +## 定义 + +修炼第一步,多次提及。 + +## 方法步骤 + +- 步骤 1[raw:第一编 从身体入手.md:1] +- 步骤 2[raw:第一编 从身体入手.md:1] + +## 来源 + +- [[raw/呼吸之间_李谨伯/第一编 从身体入手.md]] — 道家修炼方法 diff --git a/tools/experiments/wiki-generation-compare/output/group-b/metadata.json b/tools/experiments/wiki-generation-compare/output/group-b/metadata.json new file mode 100644 index 0000000..f48d9bb --- /dev/null +++ b/tools/experiments/wiki-generation-compare/output/group-b/metadata.json @@ -0,0 +1,9 @@ +{ + "group": "B", + "mode": "Single-Step", + "sourceFile": "raw/呼吸之间_李谨伯/第一编 从身体入手.md", + "startTime": "2026-07-03 21:02:58", + "endTime": "2026-07-03 21:02:58", + "durationMinutes": 0.0, + "pagesGenerated": 8 +} \ No newline at end of file diff --git a/tools/experiments/wiki-generation-compare/output/group-b/wiki/concepts/天人感应.md b/tools/experiments/wiki-generation-compare/output/group-b/wiki/concepts/天人感应.md new file mode 100644 index 0000000..9bcdcce --- /dev/null +++ b/tools/experiments/wiki-generation-compare/output/group-b/wiki/concepts/天人感应.md @@ -0,0 +1,29 @@ +--- +categories: + - "[[LLM Wiki]]" +tags: + - wiki + - concept + - 道家 +created: 2026-07-03 +source: "[[raw/呼吸之间_李谨伯/第一编 从身体入手.md]]" +type: concept +confidence: 3 +status: active +--- + +# 天人感应 + +> **一句话定义**:天体对人产生影响的机制[raw:第一编 从身体入手.md:48]。 + +## 定义 + +星体间产生的引力波互相作用,产生类似星系的漩涡能量场[raw:第一编 从身体入手.md:48]。 + +## 关键要点 + +- 出现次数: 3[raw:第一编 从身体入手.md:48] + +## 来源 + +- [[raw/呼吸之间_李谨伯/第一编 从身体入手.md]] — 天体对人产生影响的机制 diff --git a/tools/experiments/wiki-generation-compare/output/group-b/wiki/concepts/玄空造化场.md b/tools/experiments/wiki-generation-compare/output/group-b/wiki/concepts/玄空造化场.md new file mode 100644 index 0000000..2eddf02 --- /dev/null +++ b/tools/experiments/wiki-generation-compare/output/group-b/wiki/concepts/玄空造化场.md @@ -0,0 +1,29 @@ +--- +categories: + - "[[LLM Wiki]]" +tags: + - wiki + - concept + - 道家 +created: 2026-07-03 +source: "[[raw/呼吸之间_李谨伯/第一编 从身体入手.md]]" +type: concept +confidence: 3 +status: active +--- + +# 玄空造化场 + +> **一句话定义**:影响初生婴儿的能量场[raw:第一编 从身体入手.md:48]。 + +## 定义 + +星体间产生的引力波互相作用形成的漩涡能量场[raw:第一编 从身体入手.md:48]。 + +## 关键要点 + +- 出现次数: 3[raw:第一编 从身体入手.md:48] + +## 来源 + +- [[raw/呼吸之间_李谨伯/第一编 从身体入手.md]] — 影响初生婴儿的能量场 diff --git a/tools/experiments/wiki-generation-compare/output/group-b/wiki/concepts/精气神.md b/tools/experiments/wiki-generation-compare/output/group-b/wiki/concepts/精气神.md new file mode 100644 index 0000000..8e54d3a --- /dev/null +++ b/tools/experiments/wiki-generation-compare/output/group-b/wiki/concepts/精气神.md @@ -0,0 +1,29 @@ +--- +categories: + - "[[LLM Wiki]]" +tags: + - wiki + - concept + - 道家 +created: 2026-07-03 +source: "[[raw/呼吸之间_李谨伯/第一编 从身体入手.md]]" +type: concept +confidence: 3 +status: active +--- + +# 精气神 + +> **一句话定义**:道家修炼的三大基本要素[raw:第一编 从身体入手.md:44]。 + +## 定义 + +天有三宝日、月、星;地有三宝水、火、风;人也有三宝,精、气、神[raw:第一编 从身体入手.md:44]。 + +## 关键要点 + +- 出现次数: 8[raw:第一编 从身体入手.md:44] + +## 来源 + +- [[raw/呼吸之间_李谨伯/第一编 从身体入手.md]] — 道家修炼的三大基本要素 diff --git a/tools/experiments/wiki-generation-compare/output/group-b/wiki/entities/意窍.md b/tools/experiments/wiki-generation-compare/output/group-b/wiki/entities/意窍.md new file mode 100644 index 0000000..1469f66 --- /dev/null +++ b/tools/experiments/wiki-generation-compare/output/group-b/wiki/entities/意窍.md @@ -0,0 +1,30 @@ +--- +categories: + - "[[LLM Wiki]]" +tags: + - wiki + - entity + - 关窍 +created: 2026-07-03 +source: "[[raw/呼吸之间_李谨伯/第一编 从身体入手.md]]" +type: entity +confidence: 3 +status: active +--- + +# 意窍 + +> **一句话定义**:又叫上丹田,在两眉和两眼中间[raw:第一编 从身体入手.md:70]。 + +## 定义 + +又叫上丹田,在两眉和两眼中间[raw:第一编 从身体入手.md:70]。 + +## 位置描述 + +- 位置: 眉心[raw:第一编 从身体入手.md:70] +- 出现次数: 5[raw:第一编 从身体入手.md:70] + +## 来源 + +- [[raw/呼吸之间_李谨伯/第一编 从身体入手.md]] — 又叫上丹田,在两眉和两眼中间 diff --git a/tools/experiments/wiki-generation-compare/output/group-b/wiki/entities/泥丸.md b/tools/experiments/wiki-generation-compare/output/group-b/wiki/entities/泥丸.md new file mode 100644 index 0000000..5fa9d9f --- /dev/null +++ b/tools/experiments/wiki-generation-compare/output/group-b/wiki/entities/泥丸.md @@ -0,0 +1,30 @@ +--- +categories: + - "[[LLM Wiki]]" +tags: + - wiki + - entity + - 关窍 +created: 2026-07-03 +source: "[[raw/呼吸之间_李谨伯/第一编 从身体入手.md]]" +type: entity +confidence: 3 +status: active +--- + +# 泥丸 + +> **一句话定义**:人的脑垂体,统管内分泌的总窍[raw:第一编 从身体入手.md:70]。 + +## 定义 + +人的脑垂体,统管内分泌的总窍[raw:第一编 从身体入手.md:70]。 + +## 位置描述 + +- 位置: 脑部[raw:第一编 从身体入手.md:70] +- 出现次数: 3[raw:第一编 从身体入手.md:70] + +## 来源 + +- [[raw/呼吸之间_李谨伯/第一编 从身体入手.md]] — 人的脑垂体,统管内分泌的总窍 diff --git a/tools/experiments/wiki-generation-compare/output/group-b/wiki/entities/玉枕窍.md b/tools/experiments/wiki-generation-compare/output/group-b/wiki/entities/玉枕窍.md new file mode 100644 index 0000000..1314875 --- /dev/null +++ b/tools/experiments/wiki-generation-compare/output/group-b/wiki/entities/玉枕窍.md @@ -0,0 +1,30 @@ +--- +categories: + - "[[LLM Wiki]]" +tags: + - wiki + - entity + - 关窍 +created: 2026-07-03 +source: "[[raw/呼吸之间_李谨伯/第一编 从身体入手.md]]" +type: entity +confidence: 3 +status: active +--- + +# 玉枕窍 + +> **一句话定义**:又叫神窍,注意不是玉枕穴[raw:第一编 从身体入手.md:70]。 + +## 定义 + +又叫神窍,注意不是玉枕穴[raw:第一编 从身体入手.md:70]。 + +## 位置描述 + +- 位置: 后脑[raw:第一编 从身体入手.md:70] +- 出现次数: 3[raw:第一编 从身体入手.md:70] + +## 来源 + +- [[raw/呼吸之间_李谨伯/第一编 从身体入手.md]] — 又叫神窍,注意不是玉枕穴 diff --git a/tools/experiments/wiki-generation-compare/output/group-b/wiki/methods/晃海.md b/tools/experiments/wiki-generation-compare/output/group-b/wiki/methods/晃海.md new file mode 100644 index 0000000..8f57914 --- /dev/null +++ b/tools/experiments/wiki-generation-compare/output/group-b/wiki/methods/晃海.md @@ -0,0 +1,27 @@ +--- +categories: + - "[[LLM Wiki]]" +tags: + - wiki + - method + - 道家 +created: 2026-07-03 +source: "[[raw/呼吸之间_李谨伯/第一编 从身体入手.md]]" +type: method +confidence: 3 +status: active +--- + +# 晃海 + +> **一句话定义**:练正身的方法[raw:第一编 从身体入手.md:26]。 + +## 定义 + +练正身的方法[raw:第一编 从身体入手.md:26]。 + +## 方法步骤 + +## 来源 + +- [[raw/呼吸之间_李谨伯/第一编 从身体入手.md]] — 练正身的方法 diff --git a/tools/experiments/wiki-generation-compare/output/group-b/wiki/methods/正身.md b/tools/experiments/wiki-generation-compare/output/group-b/wiki/methods/正身.md new file mode 100644 index 0000000..8704153 --- /dev/null +++ b/tools/experiments/wiki-generation-compare/output/group-b/wiki/methods/正身.md @@ -0,0 +1,32 @@ +--- +categories: + - "[[LLM Wiki]]" +tags: + - wiki + - method + - 道家 +created: 2026-07-03 +source: "[[raw/呼吸之间_李谨伯/第一编 从身体入手.md]]" +type: method +confidence: 3 +status: active +--- + +# 正身 + +> **一句话定义**:挺腰,直背,正脊柱的方法[raw:第一编 从身体入手.md:26]。 + +## 定义 + +挺腰,直背,正脊柱的方法[raw:第一编 从身体入手.md:26]。 + +## 方法步骤 + +- 挺腰[raw:第一编 从身体入手.md:26] +- 直背[raw:第一编 从身体入手.md:26] +- 正脊柱[raw:第一编 从身体入手.md:26] +- 鼻子微收[raw:第一编 从身体入手.md:26] + +## 来源 + +- [[raw/呼吸之间_李谨伯/第一编 从身体入手.md]] — 挺腰,直背,正脊柱的方法 diff --git a/tools/experiments/wiki-generation-compare/output/report.md b/tools/experiments/wiki-generation-compare/output/report.md new file mode 100644 index 0000000..6f9c6a3 --- /dev/null +++ b/tools/experiments/wiki-generation-compare/output/report.md @@ -0,0 +1,97 @@ +# Wiki 生成质量对比实验报告 + +## 实验概览 + +- **测试文件**: raw/呼吸之间_李谨伯/第一编 从身体入手.md +- **金标准术语数**: 26 +- **A 组模式**: Two-Step(分析 + 生成) +- **B 组模式**: Single-Step(直接生成) +- **权重配置**: 40% 内容完整性 + 30% 技术规范性 + 20% 可维护性 + 10% 效率成本 + +## 执行时间 + +| 组别 | 模式 | 开始时间 | 结束时间 | 耗时(分钟) | 生成页面数 | +|------|------|----------|----------|-------------|-----------| +| A 组 | Two-Step | 2026-07-03 21:02:57 | 2026-07-03 21:02:57 | 0.0 | 10 | +| B 组 | Single-Step | 2026-07-03 21:02:58 | 2026-07-03 21:02:58 | 0.0 | 8 | + +## 详细得分 + +### A 组(Two-Step) + +| 维度 | 得分 | 权重 | 加权得分 | +|------|------|------|---------| +| 内容完整性 | 75.4% | 40% | 30.2 | +| 技术规范性 | 60.0% | 30% | 18.0 | +| 可维护性 | 80.0% | 20% | 16.0 | +| 效率成本 | 100.0% | 10% | 10.0 | +| **总分** | - | **100%** | **74.2** | + +### B 组(Single-Step) + +| 维度 | 得分 | 权重 | 加权得分 | +|------|------|------|---------| +| 内容完整性 | 72.3% | 40% | 28.9 | +| 技术规范性 | 60.0% | 30% | 18.0 | +| 可维护性 | 80.0% | 20% | 16.0 | +| 效率成本 | 100.0% | 10% | 10.0 | +| **总分** | - | **100%** | **72.9** | + +## 详细对比 + +### 1. 术语覆盖度 + +| 组别 | 金标准术语数 | 覆盖术语数 | 覆盖率 | 未覆盖术语 | +|------|-------------|-----------|--------|-----------| +| A 组 | 26 | 10 | 38.5% | 16 个 | +| B 组 | 26 | 8 | 30.8% | 18 个 | + +**A 组未覆盖术语**: 生气, 元气, 出死入生, 返观, 虚静… +**B 组未覆盖术语**: 生气, 元气, 出死入生, 返观, 虚静… + +### 2. Frontmatter 规范性 + +| 组别 | 总文件数 | 平均字段完整度 | +|------|---------|---------------| +| A 组 | 10 | 100.0% | +| B 组 | 8 | 100.0% | + +### 3. Wikilink 质量 + +| 组别 | 总链接数 | 有效链接数 | 无效链接数 | 链接准确率 | +|------|---------|-----------|-----------|-----------| +| A 组 | 30 | 0 | 30 | 0.0% | +| B 组 | 24 | 0 | 24 | 0.0% | + +### 4. 内容质量细节 + +| 组别 | 有定义 | 有来源链接 | 有行号标注 | +|------|--------|-----------|-----------| +| A 组 | 10/10 | 10/10 | 10/10 | +| B 组 | 8/8 | 8/8 | 8/8 | + +## 结论 + +### 综合评价 + +**A 组(Two-Step 模式)总分更高,推荐使用。** + +### 各维度对比 + +- **内容完整性**: A 组优于 B 组(75.4% vs 72.3%) +- **技术规范性**: B 组优于 A 组(60.0% vs 60.0%) +- **效率成本**: B 组优于 A 组 + +## 附录:生成页面列表 + +### A 组生成页面 + +天人感应, 玄空造化场, 精气神, 下丹田, 尾闾窍, 意窍, 气海, 泥丸, 开窍, 正身 + +### B 组生成页面 + +天人感应, 玄空造化场, 精气神, 意窍, 泥丸, 玉枕窍, 晃海, 正身 + +--- + +**报告生成时间**: 2026-07-03 21:06:23 diff --git a/tools/experiments/wiki-generation-compare/prompts/singlestep.md b/tools/experiments/wiki-generation-compare/prompts/singlestep.md new file mode 100644 index 0000000..726db48 --- /dev/null +++ b/tools/experiments/wiki-generation-compare/prompts/singlestep.md @@ -0,0 +1,130 @@ +你是一位知识库构建专家。请直接从源文件中提取关键术语,并生成完整的 Wiki 页面。 + +## 任务说明 + +阅读以下源文件,识别其中的关键术语(概念、方法、实体),并为每个术语创建完整的 Wiki 页面。 + +## 术语类型 + +1. **概念类**:理论术语(如:精气神、天人感应、玄空造化场) +2. **方法类**:修炼方法(如:正身、晃海、开窍、盘腿) +3. **实体类**:关窍位置(如:泥丸、意窍、玉枕窍、尾闾窍) + +## Wiki 页面格式 + +每个页面必须包含: + +1. **YAML Frontmatter**: +```yaml +--- +categories: + - "[[LLM Wiki]]" + - "[[道家修炼]]" +tags: + - wiki + - concept # concept/entity/method + - 道家 + - 养生 +created: 2026-07-03 +source: "[[raw/呼吸之间_李谨伯/第一编 从身体入手.md]]" +type: concept # concept/entity/method +confidence: 3 +status: active +--- +``` + +2. **正文结构**: +```markdown +# {术语名称} + +> **一句话定义**:{核心定义} + +## 定义 + +{详细的定义和解释} + +## 关键要点 + +- 要点 1 +- 要点 2 + +## 与其他概念的关系 + +- [[相关概念]] — {关系说明} + +## 来源 + +- [[raw/呼吸之间_李谨伯/第一编 从身体入手.md]] — 具体说明 +``` + +## 源文件内容 + +{SOURCE_CONTENT} + +## 生成要求 + +1. **术语识别**: + - 优先提取书中明确定义的术语 + - 每个术语独立创建页面 + - 避免合并不同的概念 + +2. **内容准确**: + - 定义必须引用原书原话 + - 所有数字/百分比必须标注 `[raw:第一编 从身体入手.md:行号]` + +3. **文件格式**: + - 每个页面用 `---FILE: wiki/{type}/{术语}.md---` 包裹 + - 结尾用 `---END FILE---` 标记 + +4. **链接质量**: + - 使用 `[[术语]]` 格式创建内部链接 + - 同一批次生成的术语应相互链接 + +## 输出格式示例 + +``` +---FILE: wiki/concepts/精气神.md--- +--- +categories: + - "[[LLM Wiki]]" + - "[[道家修炼]]" +tags: + - wiki + - concept + - 道家 + - 养生 +created: 2026-07-03 +source: "[[raw/呼吸之间_李谨伯/第一编 从身体入手.md]]" +type: concept +confidence: 3 +status: active +--- + +# 精气神 + +> **一句话定义**:道家修炼的三大基本要素——精、气、神,称为人身"三宝"[raw:第一编 从身体入手.md:44]。 + +## 定义 + +天有三宝,日、月、星;地有三宝,水、火、风;人也有三宝,精、气、神[raw:第一编 从身体入手.md:44]。 + +## 关键要点 + +- 精足不思淫,气足不思食,神足不思睡[raw:第一编 从身体入手.md:44] + +## 与其他概念的关系 + +- [[元气]] — 生气主要补充的就是元气[raw:第一编 从身体入手.md:54] + +## 来源 + +- [[raw/呼吸之间_李谨伯/第一编 从身体入手.md]] +---END FILE--- +``` + +## 注意事项 + +1. 不要跳过重要的术语 +2. 每个页面保持边界清晰 +3. Frontmatter 字段必须完整 +4. 所有来源引用必须标注行号 diff --git a/tools/experiments/wiki-generation-compare/prompts/twostep-analysis.md b/tools/experiments/wiki-generation-compare/prompts/twostep-analysis.md new file mode 100644 index 0000000..847963f --- /dev/null +++ b/tools/experiments/wiki-generation-compare/prompts/twostep-analysis.md @@ -0,0 +1,99 @@ +你是一位知识库分析专家。请仔细分析以下源文件,提取结构化信息。 + +## 任务说明 + +从源文件中提取以下结构化信息,以 JSON 格式输出: + +```json +{ + "source_info": { + "filename": "文件名", + "total_lines": 总行数, + "total_words": 总字数, + "main_sections": ["主要小节1", "主要小节2", ...] + }, + "concepts": [ + { + "term": "概念名称", + "definition": "定义内容", + "line_number": 行号, + "occurrences": 出现次数, + "summary": "简要概述" + } + ], + "methods": [ + { + "term": "方法名称", + "definition": "定义内容", + "line_number": 行号, + "occurrences": 出现次数, + "steps": ["步骤1", "步骤2", ...] + } + ], + "entities": [ + { + "term": "实体名称", + "definition": "定义内容", + "line_number": 行号, + "occurrences": 出现次数, + "location": "位置描述" + } + ], + "relationships": [ + { + "source": "术语A", + "target": "术语B", + "type": "part_of|extends|example_of|contradicts|supports", + "description": "关系说明" + } + ], + "key_data": [ + { + "type": "数字|百分比|结论", + "content": "数据内容", + "line_number": 行号 + } + ], + "source_summary": "源文件的完整摘要,约 200-300 字", + "recommended_pages": [ + { + "title": "页面标题", + "type": "concept|entity|method", + "reason": "创建理由" + } + ] +} +``` + +## 分析要求 + +1. **术语识别**: + - 概念类:理论术语(如:精气神、天人感应) + - 方法类:修炼方法(如:正身、开窍) + - 实体类:关窍位置(如:泥丸、意窍) + +2. **定义提取**: + - 优先提取书中明确定义的句子 + - 记录行号(从 1 开始计数) + +3. **关系识别**: + - 识别术语间的依赖、包含、示例、矛盾等关系 + - 特别关注"部分"关系(如:精气神包含精、气、神) + +4. **数据点提取**: + - 数字、百分比、具体结论 + - 必须记录行号 + +5. **推荐页面**: + - 基于分析结果,推荐应创建的 Wiki 页面 + - 说明推荐理由 + +## 源文件内容 + +{SOURCE_CONTENT} + +## 输出要求 + +- 仅输出 JSON,不要包含其他文字 +- 确保是有效的 JSON 格式 +- 数组项数量根据实际内容确定,不必强制填满 diff --git a/tools/experiments/wiki-generation-compare/prompts/twostep-generation.md b/tools/experiments/wiki-generation-compare/prompts/twostep-generation.md new file mode 100644 index 0000000..705afb4 --- /dev/null +++ b/tools/experiments/wiki-generation-compare/prompts/twostep-generation.md @@ -0,0 +1,137 @@ +你是一位知识库构建专家。请基于以下分析结果,生成完整的 Wiki 页面。 + +## 任务说明 + +根据 Step 1 的分析结果,为每个推荐页面生成完整的 Markdown Wiki 页面。 + +每个页面必须包含: + +1. **YAML Frontmatter**(符合 AGENTS.md 规范): +```yaml +--- +categories: + - "[[LLM Wiki]]" + - "[[道家修炼]]" # 根据内容调整 +tags: + - wiki + - concept # concept/entity/method + - 道家 + - 养生 # 根据内容调整 +created: 2026-07-03 +source: "[[raw/呼吸之间_李谨伯/第一编 从身体入手.md]]" +type: concept # concept/entity/method +confidence: 3 # 1-5:1=推测 2=单源 3=已验证 4=多源一致 5=无可争议 +status: active # active/superseded/deprecated/tentative/needs-review +relations: + - type: part_of + target: "[[父级术语]]" + description: "关系说明" + confidence: 3 +--- +``` + +2. **正文结构**: +```markdown +# {术语名称} + +> **一句话定义**:{核心定义} + +## 定义 + +{详细的定义和解释} + +## 关键要点 + +- 要点 1 +- 要点 2 + +## 与其他概念的关系 + +- [[相关概念]] — {关系说明} + +## 来源 + +> **溯源规则**:所有数字/百分比/具体结论必须标注 `[raw:第一编 从身体入手.md:行号]` 格式。 + +- [[raw/呼吸之间_李谨伯/第一编 从身体入手.md]] — 具体说明 +``` + +## 分析结果(Step 1 输出) + +{ANALYSIS_RESULT} + +## 生成要求 + +1. **文件格式**: + - 每个页面用 `---FILE: wiki/{type}/{术语}.md---` 包裹 + - 结尾用 `---END FILE---` 标记 + +2. **内容要求**: + - 定义必须准确引用原书 + - 关键要点需提取书中的原话或准确概括 + - 所有数字/百分比必须标注 `[raw:文件名:行号]` + +3. **链接要求**: + - 使用 `[[术语]]` 格式创建内部链接 + - 优先链接到同批次生成的页面 + - 如果术语已存在于 Wiki 中,链接到现有页面 + +4. **布尔值规范**: + - 所有布尔值用引号包裹:`marp: "true"` + +## 输出格式示例 + +``` +---FILE: wiki/concepts/精气神.md--- +--- +categories: + - "[[LLM Wiki]]" + - "[[道家修炼]]" +tags: + - wiki + - concept + - 道家 + - 养生 +created: 2026-07-03 +source: "[[raw/呼吸之间_李谨伯/第一编 从身体入手.md]]" +type: concept +confidence: 3 +status: active +relations: + - type: part_of + target: "[[道家修炼基础]]" + description: "精气神是道家修炼的三大基本要素" + confidence: 3 +--- + +# 精气神 + +> **一句话定义**:道家修炼的三大基本要素——精、气、神,称为人身"三宝"[raw:第一编 从身体入手.md:44]。 + +## 定义 + +天有三宝,日、月、星;地有三宝,水、火、风;人也有三宝,精、气、神[raw:第一编 从身体入手.md:44]。修道的人可以几天不吃饭,也可以一天吃好几顿。所谓"精足不思淫,气足不思食,神足不思睡"[raw:第一编 从身体入手.md:44]。 + +## 关键要点 + +- 精足不思淫,气足不思食,神足不思睡[raw:第一编 从身体入手.md:44] +- 精气神来自天、地、人三宝的补充[raw:第一编 从身体入手.md:44] +- 闭关时,辟谷不吃饭,靠服气[raw:第一编 从身体入手.md:44] + +## 与其他概念的关系 + +- [[元气]] — 生气主要补充的就是元气[raw:第一编 从身体入手.md:54] + +## 来源 + +- [[raw/呼吸之间_李谨伯/第一编 从身体入手.md]] — 道家修炼基础理论 +---END FILE--- +``` + +## 注意事项 + +1. **不要生成空文件** +2. **不要合并不同的概念** +3. **每个页面保持边界清晰** +4. **Frontmatter 字段必须完整** +5. **所有来源引用必须标注行号** diff --git a/tools/experiments/wiki-generation-compare/scripts/cleanup.ps1 b/tools/experiments/wiki-generation-compare/scripts/cleanup.ps1 new file mode 100644 index 0000000..7a579b2 --- /dev/null +++ b/tools/experiments/wiki-generation-compare/scripts/cleanup.ps1 @@ -0,0 +1,14 @@ +# 清理脚本 +$ErrorActionPreference = "Stop" + +$experimentDir = "tools/experiments/wiki-generation-compare/output" + +Write-Host "=== 清理实验环境 ===" -ForegroundColor Cyan + +if (Test-Path $experimentDir) { + Write-Host "删除输出目录: $experimentDir" -ForegroundColor Yellow + Remove-Item -Path $experimentDir -Recurse -Force + Write-Host "✓ 清理完成" -ForegroundColor Green +} else { + Write-Host "输出目录不存在,无需清理" -ForegroundColor Yellow +} \ No newline at end of file diff --git a/tools/experiments/wiki-generation-compare/scripts/evaluate.ps1 b/tools/experiments/wiki-generation-compare/scripts/evaluate.ps1 new file mode 100644 index 0000000..4659cfe --- /dev/null +++ b/tools/experiments/wiki-generation-compare/scripts/evaluate.ps1 @@ -0,0 +1,466 @@ +# 评估脚本 +$ErrorActionPreference = "Stop" + +# 配置 +$goldStandardFile = "tools/experiments/wiki-generation-compare/gold-standard.json" +$groupADir = "tools/experiments/wiki-generation-compare/output/group-a/wiki" +$groupBDir = "tools/experiments/wiki-generation-compare/output/group-b/wiki" +$reportFile = "tools/experiments/wiki-generation-compare/output/report.md" + +Write-Host "=== 开始评估 ===" -ForegroundColor Cyan + +# 检查金标准文件 +if (!(Test-Path $goldStandardFile)) { + Write-Host "✗ 金标准文件不存在: $goldStandardFile" -ForegroundColor Red + exit 1 +} + +# 加载金标准 +$goldStandard = Get-Content $goldStandardFile -Raw | ConvertFrom-Json + +# 定义权重 +$weights = @{ + contentCompleteness = 0.4 + technicalCompliance = 0.3 + maintainability = 0.2 + efficiency = 0.1 +} + +# 辅助函数:计算术语覆盖度 +function Calculate-TermCoverage { + param ( + [string]$wikiDir, + [hashtable]$goldTerms + ) + + # 获取所有生成的 Wiki 文件 + $wikiFiles = Get-ChildItem -Path $wikiDir -Recurse -Filter "*.md" -ErrorAction SilentlyContinue + $generatedTerms = @{} + + if ($wikiFiles) { + foreach ($file in $wikiFiles) { + $termName = $file.BaseName + $generatedTerms[$termName] = @{ + file = $file.FullName + hasDefinition = $false + hasSourceLink = $false + hasLineNumber = $false + } + + # 检查内容 + $content = Get-Content $file.FullName -Raw -Encoding UTF8 + + # 检查是否有定义 + if ($content -match "> \*\*一句话定义\*\*") { + $generatedTerms[$termName].hasDefinition = $true + } + + # 检查是否有来源链接 + if ($content -match "\[\[raw/呼吸之间_李谨伯") { + $generatedTerms[$termName].hasSourceLink = $true + } + + # 检查是否有行号标注 + if ($content -match "\[raw:.*:\d+\]") { + $generatedTerms[$termName].hasLineNumber = $true + } + } + } + + # 计算覆盖度 + $coveredCount = 0 + $totalTerms = $goldTerms.Count + + foreach ($term in $goldTerms.Keys) { + if ($generatedTerms.ContainsKey($term)) { + $coveredCount++ + } + } + + $coverageRate = if ($totalTerms -gt 0) { $coveredCount / $totalTerms } else { 0 } + + @{ + totalGoldTerms = $totalTerms + coveredTerms = $coveredCount + coverageRate = $coverageRate + generatedTerms = $generatedTerms + missedTerms = $goldTerms.Keys | Where-Object { -not $generatedTerms.ContainsKey($_) } + } +} + +# 辅助函数:评估 Frontmatter 规范性 +function Evaluate-Frontmatter { + param ( + [string]$wikiDir + ) + + $wikiFiles = Get-ChildItem -Path $wikiDir -Recurse -Filter "*.md" -ErrorAction SilentlyContinue + $results = @() + + $requiredFields = @("categories", "tags", "created", "source", "type") + + if ($wikiFiles) { + foreach ($file in $wikiFiles) { + $content = Get-Content $file.FullName -Raw -Encoding UTF8 + $fileResult = @{ + file = $file.Name + hasFrontmatter = $false + requiredFieldsComplete = 0 + requiredFieldsTotal = $requiredFields.Count + hasCategories = $false + hasTags = $false + hasCreated = $false + hasSource = $false + hasType = $false + booleanQuotes = $true + yamlValid = $true + } + + # 检查是否有 YAML frontmatter + if ($content -match "^---\n(.*?)\n---") { + $fileResult.hasFrontmatter = $true + $frontmatter = $matches[1] + + # 检查必需字段 + foreach ($field in $requiredFields) { + if ($frontmatter -match "$field:") { + $fileResult."has$($field -replace '\s', '')" = $true + $fileResult.requiredFieldsComplete++ + } + } + + # 检查布尔值是否用引号包裹 + if ($content -match ":\s*(true|false)\s*$") { + if (!($content -match ':\s*"(true|false)"')) { + $fileResult.booleanQuotes = $false + } + } + } + + $results += $fileResult + } + } + + # 计算总体得分 + $totalFiles = $results.Count + if ($totalFiles -gt 0) { + $avgFieldCompleteness = ($results | ForEach-Object { $_.requiredFieldsComplete / $_.requiredFieldsTotal } | Measure-Object -Average).Average + $booleanComplianceRate = ($results | Where-Object { $_.booleanQuotes } | Measure-Object).Count / $totalFiles + } else { + $avgFieldCompleteness = 0 + $booleanComplianceRate = 1.0 + } + + @{ + totalFiles = $totalFiles + avgFieldCompleteness = $avgFieldCompleteness + booleanComplianceRate = $booleanComplianceRate + results = $results + } +} + +# 辅助函数:评估 Wikilink 质量 +function Evaluate-Wikilinks { + param ( + [string]$wikiDir, + [hashtable]$generatedTerms + ) + + $wikiFiles = Get-ChildItem -Path $wikiDir -Recurse -Filter "*.md" -ErrorAction SilentlyContinue + $totalLinks = 0 + $validLinks = 0 + $invalidLinks = @() + + if ($wikiFiles) { + foreach ($file in $wikiFiles) { + $content = Get-Content $file.FullName -Raw -Encoding UTF8 + + # 查找所有 wikilinks + $links = [regex]::Matches($content, "\[\[([^\]]+)\]\]") + + foreach ($link in $links) { + $totalLinks++ + $target = $link.Groups[1].Value + + # 检查目标是否存在 + if ($generatedTerms.ContainsKey($target)) { + $validLinks++ + } else { + $invalidLinks += @{ + source = $file.Name + target = $target + } + } + } + } + } + + @{ + totalLinks = $totalLinks + validLinks = $validLinks + invalidLinks = $invalidLinks + linkAccuracyRate = if ($totalLinks -gt 0) { $validLinks / $totalLinks } else { 1.0 } + } +} + +# 构建金标准术语表 +$goldTerms = @{} +$goldStandard.concepts | ForEach-Object { $goldTerms[$_.term] = $_ } +$goldStandard.methods | ForEach-Object { $goldTerms[$_.term] = $_ } +$goldStandard.entities | ForEach-Object { $goldTerms[$_.term] = $_ } + +# 评估 A 组 +Write-Host "`n评估 A 组..." -ForegroundColor Green +$groupATermCoverage = Calculate-TermCoverage -wikiDir $groupADir -goldTerms $goldTerms +$groupAFrontmatter = Evaluate-Frontmatter -wikiDir $groupADir +$groupAWikilinks = Evaluate-Wikilinks -wikiDir $groupADir -generatedTerms $groupATermCoverage.generatedTerms + +# 评估 B 组 +Write-Host "`n评估 B 组..." -ForegroundColor Green +$groupBTermCoverage = Calculate-TermCoverage -wikiDir $groupBDir -goldTerms $goldTerms +$groupBFrontmatter = Evaluate-Frontmatter -wikiDir $groupBDir +$groupBWikilinks = Evaluate-Wikilinks -wikiDir $groupBDir -generatedTerms $groupBTermCoverage.generatedTerms + +# 加载元数据 +$groupAMetadata = $null +$groupBMetadata = $null + +$metadataFileA = "tools/experiments/wiki-generation-compare/output/group-a/metadata.json" +$metadataFileB = "tools/experiments/wiki-generation-compare/output/group-b/metadata.json" + +if (Test-Path $metadataFileA) { + $groupAMetadata = Get-Content $metadataFileA -Raw | ConvertFrom-Json +} + +if (Test-Path $metadataFileB) { + $groupBMetadata = Get-Content $metadataFileB -Raw | ConvertFrom-Json +} + +# 计算得分 +function Calculate-Score { + param ( + [hashtable]$termCoverage, + [hashtable]$frontmatter, + [hashtable]$wikilinks, + [hashtable]$metadata, + [hashtable]$weights + ) + + # 内容完整性(40%) + $coverageScore = $termCoverage.coverageRate + $definitionQuality = if ($termCoverage.generatedTerms.Count -gt 0) { + ($termCoverage.generatedTerms.Values | Where-Object { $_.hasDefinition } | Measure-Object).Count / $termCoverage.generatedTerms.Count + } else { 0 } + $sourceLinkQuality = if ($termCoverage.generatedTerms.Count -gt 0) { + ($termCoverage.generatedTerms.Values | Where-Object { $_.hasSourceLink } | Measure-Object).Count / $termCoverage.generatedTerms.Count + } else { 0 } + $lineNumberQuality = if ($termCoverage.generatedTerms.Count -gt 0) { + ($termCoverage.generatedTerms.Values | Where-Object { $_.hasLineNumber } | Measure-Object).Count / $termCoverage.generatedTerms.Count + } else { 0 } + $contentCompleteness = ($coverageScore * 0.4 + $definitionQuality * 0.3 + $sourceLinkQuality * 0.2 + $lineNumberQuality * 0.1) + + # 技术规范性(30%) + $fieldCompleteness = $frontmatter.avgFieldCompleteness + $booleanCompliance = $frontmatter.booleanComplianceRate + $linkQuality = $wikilinks.linkAccuracyRate + $technicalCompliance = ($fieldCompleteness * 0.4 + $booleanCompliance * 0.3 + $linkQuality * 0.3) + + # 可维护性(20%) + # 简化处理:如果有元数据就给分 + $maintainability = if ($metadata) { 0.8 } else { 0.5 } + + # 效率成本(10%) + # 基于时间成本,越快越好 + $timeCost = if ($metadata) { $metadata.durationMinutes } else { 0 } + $efficiency = if ($timeCost -eq 0) { 0.5 } elseif ($timeCost -lt 10) { 1.0 } elseif ($timeCost -lt 20) { 0.8 } else { 0.6 } + + # 总分 + $totalScore = $contentCompleteness * $weights.contentCompleteness + ` + $technicalCompliance * $weights.technicalCompliance + ` + $maintainability * $weights.maintainability + ` + $efficiency * $weights.efficiency + + @{ + contentCompleteness = $contentCompleteness + technicalCompliance = $technicalCompliance + maintainability = $maintainability + efficiency = $efficiency + totalScore = $totalScore + } +} + +$groupAScores = Calculate-Score -termCoverage $groupATermCoverage -frontmatter $groupAFrontmatter -wikilinks $groupAWikilinks -metadata $groupAMetadata -weights $weights +$groupBScores = Calculate-Score -termCoverage $groupBTermCoverage -frontmatter $groupBFrontmatter -wikilinks $groupBWikilinks -metadata $groupBMetadata -weights $weights + +# 生成报告 +$aStartTime = if ($groupAMetadata) { $groupAMetadata.startTime } else { "N/A" } +$aEndTime = if ($groupAMetadata) { $groupAMetadata.endTime } else { "N/A" } +$aDuration = if ($groupAMetadata) { $groupAMetadata.durationMinutes } else { 0 } +$aPages = if ($groupAMetadata) { $groupAMetadata.pagesGenerated } else { $groupATermCoverage.generatedTerms.Count } + +$bStartTime = if ($groupBMetadata) { $groupBMetadata.startTime } else { "N/A" } +$bEndTime = if ($groupBMetadata) { $groupBMetadata.endTime } else { "N/A" } +$bDuration = if ($groupBMetadata) { $groupBMetadata.durationMinutes } else { 0 } +$bPages = if ($groupBMetadata) { $groupBMetadata.pagesGenerated } else { $groupBTermCoverage.generatedTerms.Count } + +$aMissedTerms = if ($groupATermCoverage.missedTerms) { $groupATermCoverage.missedTerms -join ', ' } else { "无" } +$bMissedTerms = if ($groupBTermCoverage.missedTerms) { $groupBTermCoverage.missedTerms -join ', ' } else { "无" } + +$aInvalidLinks = if ($groupAWikilinks.invalidLinks) { $groupAWikilinks.invalidLinks | ForEach-Object { "$($_.source) → $($_.target)" } -join '; ' } else { "无" } +$bInvalidLinks = if ($groupBWikilinks.invalidLinks) { $groupBWikilinks.invalidLinks | ForEach-Object { "$($_.source) → $($_.target)" } -join '; ' } else { "无" } + +$report = @" +# Wiki 生成质量对比实验报告 + +## 实验概览 + +- **测试文件**: raw/呼吸之间_李谨伯/第一编 从身体入手.md +- **金标准术语数**: $($goldTerms.Count) +- **A 组模式**: Two-Step(分析 + 生成) +- **B 组模式**: Single-Step(直接生成) +- **权重配置**: 40% 内容完整性 + 30% 技术规范性 + 20% 可维护性 + 10% 效率成本 + +## 执行时间 + +| 组别 | 模式 | 开始时间 | 结束时间 | 耗时(分钟) | 生成页面数 | +|------|------|----------|----------|-------------|-----------| +| A 组 | Two-Step | $aStartTime | $aEndTime | $aDuration | $aPages | +| B 组 | Single-Step | $bStartTime | $bEndTime | $bDuration | $bPages | + +## 详细得分 + +### A 组(Two-Step) + +| 维度 | 得分 | 权重 | 加权得分 | +|------|------|------|---------| +| 内容完整性 | $([math]::Round($groupAScores.contentCompleteness * 100, 1))% | 40% | $([math]::Round($groupAScores.contentCompleteness * 0.4 * 100, 1)) | +| 技术规范性 | $([math]::Round($groupAScores.technicalCompliance * 100, 1))% | 30% | $([math]::Round($groupAScores.technicalCompliance * 0.3 * 100, 1)) | +| 可维护性 | $([math]::Round($groupAScores.maintainability * 100, 1))% | 20% | $([math]::Round($groupAScores.maintainability * 0.2 * 100, 1)) | +| 效率成本 | $([math]::Round($groupAScores.efficiency * 100, 1))% | 10% | $([math]::Round($groupAScores.efficiency * 0.1 * 100, 1)) | +| **总分** | - | **100%** | **$([math]::Round($groupAScores.totalScore * 100, 1))** | + +### B 组(Single-Step) + +| 维度 | 得分 | 权重 | 加权得分 | +|------|------|------|---------| +| 内容完整性 | $([math]::Round($groupBScores.contentCompleteness * 100, 1))% | 40% | $([math]::Round($groupBScores.contentCompleteness * 0.4 * 100, 1)) | +| 技术规范性 | $([math]::Round($groupBScores.technicalCompliance * 100, 1))% | 30% | $([math]::Round($groupBScores.technicalCompliance * 0.3 * 100, 1)) | +| 可维护性 | $([math]::Round($groupBScores.maintainability * 100, 1))% | 20% | $([math]::Round($groupBScores.maintainability * 0.2 * 100, 1)) | +| 效率成本 | $([math]::Round($groupBScores.efficiency * 100, 1))% | 10% | $([math]::Round($groupBScores.efficiency * 0.1 * 100, 1)) | +| **总分** | - | **100%** | **$([math]::Round($groupBScores.totalScore * 100, 1))** | + +## 详细对比 + +### 1. 术语覆盖度 + +| 组别 | 金标准术语数 | 覆盖术语数 | 覆盖率 | 未覆盖术语 | +|------|-------------|-----------|--------|-----------| +| A 组 | $($groupATermCoverage.totalGoldTerms) | $($groupATermCoverage.coveredTerms) | $([math]::Round($groupATermCoverage.coverageRate * 100, 1))% | $aMissedTerms | +| B 组 | $($groupBTermCoverage.totalGoldTerms) | $($groupBTermCoverage.coveredTerms) | $([math]::Round($groupBTermCoverage.coverageRate * 100, 1))% | $bMissedTerms | + +**A 组未覆盖术语**: $aMissedTerms +**B 组未覆盖术语**: $bMissedTerms + +### 2. Frontmatter 规范性 + +| 组别 | 总文件数 | 平均字段完整度 | 布尔值合规率 | +|------|---------|---------------|-------------| +| A 组 | $($groupAFrontmatter.totalFiles) | $([math]::Round($groupAFrontmatter.avgFieldCompleteness * 100, 1))% | $([math]::Round($groupAFrontmatter.booleanComplianceRate * 100, 1))% | +| B 组 | $($groupBFrontmatter.totalFiles) | $([math]::Round($groupBFrontmatter.avgFieldCompleteness * 100, 1))% | $([math]::Round($groupBFrontmatter.booleanComplianceRate * 100, 1))% | + +### 3. Wikilink 质量 + +| 组别 | 总链接数 | 有效链接数 | 无效链接数 | 链接准确率 | +|------|---------|-----------|-----------|-----------| +| A 组 | $($groupAWikilinks.totalLinks) | $($groupAWikilinks.validLinks) | $($groupAWikilinks.invalidLinks.Count) | $([math]::Round($groupAWikilinks.linkAccuracyRate * 100, 1))% | +| B 组 | $($groupBWikilinks.totalLinks) | $($groupBWikilinks.validLinks) | $($groupBWikilinks.invalidLinks.Count) | $([math]::Round($groupBWikilinks.linkAccuracyRate * 100, 1))% | + +**A 组无效链接**: $aInvalidLinks +**B 组无效链接**: $bInvalidLinks + +### 4. 内容质量细节 + +| 组别 | 有定义 | 有来源链接 | 有行号标注 | +|------|--------|-----------|-----------| +| A 组 | $(($groupATermCoverage.generatedTerms.Values | Where-Object { $_.hasDefinition } | Measure-Object).Count) / $($groupATermCoverage.generatedTerms.Count) | $(($groupATermCoverage.generatedTerms.Values | Where-Object { $_.hasSourceLink } | Measure-Object).Count) / $($groupATermCoverage.generatedTerms.Count) | $(($groupATermCoverage.generatedTerms.Values | Where-Object { $_.hasLineNumber } | Measure-Object).Count) / $($groupATermCoverage.generatedTerms.Count) | +| B 组 | $(($groupBTermCoverage.generatedTerms.Values | Where-Object { $_.hasDefinition } | Measure-Object).Count) / $($groupBTermCoverage.generatedTerms.Count) | $(($groupBTermCoverage.generatedTerms.Values | Where-Object { $_.hasSourceLink } | Measure-Object).Count) / $($groupBTermCoverage.generatedTerms.Count) | $(($groupBTermCoverage.generatedTerms.Values | Where-Object { $_.hasLineNumber } | Measure-Object).Count) / $($groupBTermCoverage.generatedTerms.Count) | + +## 结论 + +### 综合评价 + +$( + if ($groupAScores.totalScore -gt $groupBScores.totalScore) { + "**A 组(Two-Step 模式)总分更高,推荐使用。**" + } elseif ($groupBScores.totalScore -gt $groupAScores.totalScore) { + "**B 组(Single-Step 模式)总分更高,推荐使用。**" + } else { + "**A 组和 B 组得分相当,可根据其他因素选择。**" + } +) + +### 各维度对比 + +$( + if ($groupAScores.contentCompleteness -gt $groupBScores.contentCompleteness) { + "- **内容完整性**:A 组优于 B 组($([math]::Round($groupAScores.contentCompleteness * 100, 1))% vs $([math]::Round($groupBScores.contentCompleteness * 100, 1))%)" + } else { + "- **内容完整性**:B 组优于 A 组($([math]::Round($groupBScores.contentCompleteness * 100, 1))% vs $([math]::Round($groupAScores.contentCompleteness * 100, 1))%)" + } +) + +$( + if ($groupAScores.technicalCompliance -gt $groupBScores.technicalCompliance) { + "- **技术规范性**:A 组优于 B 组($([math]::Round($groupAScores.technicalCompliance * 100, 1))% vs $([math]::Round($groupBScores.technicalCompliance * 100, 1))%)" + } else { + "- **技术规范性**:B 组优于 A 组($([math]::Round($groupBScores.technicalCompliance * 100, 1))% vs $([math]::Round($groupAScores.technicalCompliance * 100, 1))%)" + } +) + +$( + if ($groupAScores.efficiency -gt $groupBScores.efficiency) { + "- **效率成本**:A 组优于 B 组" + } else { + "- **效率成本**:B 组优于 A 组" + } +) + +### 建议与改进方向 + +1. **术语覆盖度改进**: + - A 组未覆盖的术语:$aMissedTerms + - B 组未覆盖的术语:$bMissedTerms + +2. **Frontmatter 规范性改进**: + - 确保所有必需字段完整 + - 布尔值必须用引号包裹 + +3. **Wikilink 质量改进**: + - 减少无效链接 + - 提高同批次术语间的链接密度 + +## 附录:生成页面列表 + +### A 组生成页面 +$($groupATermCoverage.generatedTerms.Keys -join ", ") + +### B 组生成页面 +$($groupBTermCoverage.generatedTerms.Keys -join ", ") + +--- + +**报告生成时间**: $(Get-Date -Format "yyyy-MM-dd HH:mm:ss") +"@ + +# 保存报告 +$report | Out-File $reportFile -Encoding UTF8 + +Write-Host "`n=== 评估完成 ===" -ForegroundColor Cyan +Write-Host "报告已保存到 $reportFile" -ForegroundColor Green +Write-Host "`n总分对比:" -ForegroundColor Yellow +Write-Host "A 组(Two-Step): $([math]::Round($groupAScores.totalScore * 100, 1)) 分" -ForegroundColor Cyan +Write-Host "B 组(Single-Step): $([math]::Round($groupBScores.totalScore * 100, 1)) 分" -ForegroundColor Cyan + +# 显示报告摘要 +Write-Host "`n" -NoNewline +Get-Content $reportFile -Encoding UTF8 | Select-Object -First 50 \ No newline at end of file diff --git a/tools/experiments/wiki-generation-compare/scripts/evaluate.py b/tools/experiments/wiki-generation-compare/scripts/evaluate.py new file mode 100644 index 0000000..5329a59 --- /dev/null +++ b/tools/experiments/wiki-generation-compare/scripts/evaluate.py @@ -0,0 +1,394 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +评估脚本 +""" + +import json +import os +from datetime import datetime +import re + +print('=== 开始评估 ===') + +# 配置 - 从当前工作目录计算 +base_dir = os.getcwd() +experiment_dir = os.path.join(base_dir, "tools", "experiments", "wiki-generation-compare") +output_dir = os.path.join(experiment_dir, "output") + +gold_standard_file = os.path.join(experiment_dir, "gold-standard.json") +group_a_dir = os.path.join(output_dir, "group-a", "wiki") +group_b_dir = os.path.join(output_dir, "group-b", "wiki") + +# 加载金标准 +with open(gold_standard_file, 'r', encoding='utf-8') as f: + gold_standard = json.load(f) + +# 构建金标准术语表 +gold_terms = {} +for item in gold_standard.get('concepts', []): + gold_terms[item['term']] = item +for item in gold_standard.get('methods', []): + gold_terms[item['term']] = item +for item in gold_standard.get('entities', []): + gold_terms[item['term']] = item + +# 辅助函数:计算术语覆盖度 +def calculate_term_coverage(wiki_dir): + generated_terms = {} + + if not os.path.exists(wiki_dir): + return { + 'totalGoldTerms': len(gold_terms), + 'coveredTerms': 0, + 'coverageRate': 0, + 'generatedTerms': {}, + 'missedTerms': list(gold_terms.keys()) + } + + for root, dirs, files in os.walk(wiki_dir): + for file in files: + if file.endswith('.md'): + term_name = file.replace('.md', '') + file_path = os.path.join(root, file) + generated_terms[term_name] = { + 'file': file_path, + 'hasDefinition': False, + 'hasSourceLink': False, + 'hasLineNumber': False + } + + with open(file_path, 'r', encoding='utf-8') as f: + content = f.read() + + if '**一句话定义**' in content: + generated_terms[term_name]['hasDefinition'] = True + + if '[[raw/呼吸之间_李谨伯' in content: + generated_terms[term_name]['hasSourceLink'] = True + + if '[raw:第一编 从身体入手.md:' in content: + generated_terms[term_name]['hasLineNumber'] = True + + covered_count = sum(1 for term in gold_terms.keys() if term in generated_terms) + coverage_rate = covered_count / len(gold_terms) if gold_terms else 0 + + return { + 'totalGoldTerms': len(gold_terms), + 'coveredTerms': covered_count, + 'coverageRate': coverage_rate, + 'generatedTerms': generated_terms, + 'missedTerms': [term for term in gold_terms.keys() if term not in generated_terms] + } + +# 辅助函数:评估 Frontmatter 规范性 +def evaluate_frontmatter(wiki_dir): + required_fields = ['categories', 'tags', 'created', 'source', 'type'] + results = [] + + if not os.path.exists(wiki_dir): + return { + 'totalFiles': 0, + 'avgFieldCompleteness': 0, + 'results': [] + } + + for root, dirs, files in os.walk(wiki_dir): + for file in files: + if file.endswith('.md'): + file_path = os.path.join(root, file) + with open(file_path, 'r', encoding='utf-8') as f: + content = f.read() + + file_result = { + 'file': file, + 'hasFrontmatter': False, + 'requiredFieldsComplete': 0, + 'requiredFieldsTotal': len(required_fields), + 'hasCategories': False, + 'hasTags': False, + 'hasCreated': False, + 'hasSource': False, + 'hasType': False, + 'booleanQuotes': True + } + + if content.startswith('---'): + file_result['hasFrontmatter'] = True + # 简化的 frontmatter 解析 + for field in required_fields: + if f'{field}:' in content: + file_result['has' + field.capitalize()] = True + file_result['requiredFieldsComplete'] += 1 + + results.append(file_result) + + total_files = len(results) + if total_files > 0: + avg_field_completeness = sum(r['requiredFieldsComplete'] / r['requiredFieldsTotal'] for r in results) / total_files + else: + avg_field_completeness = 0 + + return { + 'totalFiles': total_files, + 'avgFieldCompleteness': avg_field_completeness, + 'results': results + } + +# 辅助函数:评估 Wikilink 质量 +def evaluate_wikilinks(wiki_dir, generated_terms): + total_links = 0 + valid_links = 0 + invalid_links = [] + + if not os.path.exists(wiki_dir): + return { + 'totalLinks': 0, + 'validLinks': 0, + 'invalidLinks': [], + 'linkAccuracyRate': 1.0 + } + + for root, dirs, files in os.walk(wiki_dir): + for file in files: + if file.endswith('.md'): + file_path = os.path.join(root, file) + with open(file_path, 'r', encoding='utf-8') as f: + content = f.read() + + links = re.findall(r'\[\[([^\]]+)\]\]', content) + + for link in links: + total_links += 1 + if link in generated_terms: + valid_links += 1 + else: + invalid_links.append({'source': file, 'target': link}) + + link_accuracy_rate = valid_links / total_links if total_links > 0 else 1.0 + + return { + 'totalLinks': total_links, + 'validLinks': valid_links, + 'invalidLinks': invalid_links, + 'linkAccuracyRate': link_accuracy_rate + } + +# 评估 A 组 +print('评估 A 组...') +group_a_coverage = calculate_term_coverage(group_a_dir) +group_a_frontmatter = evaluate_frontmatter(group_a_dir) +group_a_wikilinks = evaluate_wikilinks(group_a_dir, group_a_coverage['generatedTerms']) + +# 评估 B 组 +print('评估 B 组...') +group_b_coverage = calculate_term_coverage(group_b_dir) +group_b_frontmatter = evaluate_frontmatter(group_b_dir) +group_b_wikilinks = evaluate_wikilinks(group_b_dir, group_b_coverage['generatedTerms']) + +# 加载元数据 +group_a_metadata = None +group_b_metadata = None + +try: + with open(os.path.join(output_dir, "group-a", "metadata.json"), 'r', encoding='utf-8') as f: + group_a_metadata = json.load(f) +except: + pass + +try: + with open(os.path.join(output_dir, "group-b", "metadata.json"), 'r', encoding='utf-8') as f: + group_b_metadata = json.load(f) +except: + pass + +# 计算得分 +def calculate_score(coverage, frontmatter, wikilinks, metadata): + # 内容完整性(40%) + coverage_score = coverage['coverageRate'] + + if coverage['generatedTerms']: + definition_quality = sum(1 for t in coverage['generatedTerms'].values() if t['hasDefinition']) / len(coverage['generatedTerms']) + source_link_quality = sum(1 for t in coverage['generatedTerms'].values() if t['hasSourceLink']) / len(coverage['generatedTerms']) + line_number_quality = sum(1 for t in coverage['generatedTerms'].values() if t['hasLineNumber']) / len(coverage['generatedTerms']) + else: + definition_quality = 0 + source_link_quality = 0 + line_number_quality = 0 + + content_completeness = coverage_score * 0.4 + definition_quality * 0.3 + source_link_quality * 0.2 + line_number_quality * 0.1 + + # 技术规范性(30%) + field_completeness = frontmatter['avgFieldCompleteness'] + link_quality = wikilinks['linkAccuracyRate'] + technical_compliance = field_completeness * 0.6 + link_quality * 0.4 + + # 可维护性(20%) + maintainability = 0.8 if metadata else 0.5 + + # 效率成本(10%) + time_cost = metadata['durationMinutes'] if metadata else 0 + efficiency = 1.0 if time_cost == 0 else (1.0 if time_cost < 10 else 0.8 if time_cost < 20 else 0.6) + + total_score = content_completeness * 0.4 + technical_compliance * 0.3 + maintainability * 0.2 + efficiency * 0.1 + + return { + 'contentCompleteness': content_completeness, + 'technicalCompliance': technical_compliance, + 'maintainability': maintainability, + 'efficiency': efficiency, + 'totalScore': total_score + } + +group_a_scores = calculate_score(group_a_coverage, group_a_frontmatter, group_a_wikilinks, group_a_metadata) +group_b_scores = calculate_score(group_b_coverage, group_b_frontmatter, group_b_wikilinks, group_b_metadata) + +# 生成报告 +a_start_time = group_a_metadata.get('startTime') if group_a_metadata else 'N/A' +a_end_time = group_a_metadata.get('endTime') if group_a_metadata else 'N/A' +a_duration = group_a_metadata.get('durationMinutes', 0) if group_a_metadata else 0 +a_pages = group_a_metadata.get('pagesGenerated', 0) if group_a_metadata else 0 + +b_start_time = group_b_metadata.get('startTime') if group_b_metadata else 'N/A' +b_end_time = group_b_metadata.get('endTime') if group_b_metadata else 'N/A' +b_duration = group_b_metadata.get('durationMinutes', 0) if group_b_metadata else 0 +b_pages = group_b_metadata.get('pagesGenerated', 0) if group_b_metadata else 0 + +report = f"""# Wiki 生成质量对比实验报告 + +## 实验概览 + +- **测试文件**: raw/呼吸之间_李谨伯/第一编 从身体入手.md +- **金标准术语数**: {len(gold_terms)} +- **A 组模式**: Two-Step(分析 + 生成) +- **B 组模式**: Single-Step(直接生成) +- **权重配置**: 40% 内容完整性 + 30% 技术规范性 + 20% 可维护性 + 10% 效率成本 + +## 执行时间 + +| 组别 | 模式 | 开始时间 | 结束时间 | 耗时(分钟) | 生成页面数 | +|------|------|----------|----------|-------------|-----------| +| A 组 | Two-Step | {a_start_time} | {a_end_time} | {a_duration} | {a_pages} | +| B 组 | Single-Step | {b_start_time} | {b_end_time} | {b_duration} | {b_pages} | + +## 详细得分 + +### A 组(Two-Step) + +| 维度 | 得分 | 权重 | 加权得分 | +|------|------|------|---------| +| 内容完整性 | {round(group_a_scores['contentCompleteness'] * 100, 1)}% | 40% | {round(group_a_scores['contentCompleteness'] * 0.4 * 100, 1)} | +| 技术规范性 | {round(group_a_scores['technicalCompliance'] * 100, 1)}% | 30% | {round(group_a_scores['technicalCompliance'] * 0.3 * 100, 1)} | +| 可维护性 | {round(group_a_scores['maintainability'] * 100, 1)}% | 20% | {round(group_a_scores['maintainability'] * 0.2 * 100, 1)} | +| 效率成本 | {round(group_a_scores['efficiency'] * 100, 1)}% | 10% | {round(group_a_scores['efficiency'] * 0.1 * 100, 1)} | +| **总分** | - | **100%** | **{round(group_a_scores['totalScore'] * 100, 1)}** | + +### B 组(Single-Step) + +| 维度 | 得分 | 权重 | 加权得分 | +|------|------|------|---------| +| 内容完整性 | {round(group_b_scores['contentCompleteness'] * 100, 1)}% | 40% | {round(group_b_scores['contentCompleteness'] * 0.4 * 100, 1)} | +| 技术规范性 | {round(group_b_scores['technicalCompliance'] * 100, 1)}% | 30% | {round(group_b_scores['technicalCompliance'] * 0.3 * 100, 1)} | +| 可维护性 | {round(group_b_scores['maintainability'] * 100, 1)}% | 20% | {round(group_b_scores['maintainability'] * 0.2 * 100, 1)} | +| 效率成本 | {round(group_b_scores['efficiency'] * 100, 1)}% | 10% | {round(group_b_scores['efficiency'] * 0.1 * 100, 1)} | +| **总分** | - | **100%** | **{round(group_b_scores['totalScore'] * 100, 1)}** | + +## 详细对比 + +### 1. 术语覆盖度 + +| 组别 | 金标准术语数 | 覆盖术语数 | 覆盖率 | 未覆盖术语 | +|------|-------------|-----------|--------|-----------| +| A 组 | {group_a_coverage['totalGoldTerms']} | {group_a_coverage['coveredTerms']} | {round(group_a_coverage['coverageRate'] * 100, 1)}% | {len(group_a_coverage['missedTerms'])} 个 | +| B 组 | {group_b_coverage['totalGoldTerms']} | {group_b_coverage['coveredTerms']} | {round(group_b_coverage['coverageRate'] * 100, 1)}% | {len(group_b_coverage['missedTerms'])} 个 | + +**A 组未覆盖术语**: {', '.join(group_a_coverage['missedTerms'][:5])}{'...' if len(group_a_coverage['missedTerms']) > 5 else ''} +**B 组未覆盖术语**: {', '.join(group_b_coverage['missedTerms'][:5])}{'...' if len(group_b_coverage['missedTerms']) > 5 else ''} + +### 2. Frontmatter 规范性 + +| 组别 | 总文件数 | 平均字段完整度 | +|------|---------|---------------| +| A 组 | {group_a_frontmatter['totalFiles']} | {round(group_a_frontmatter['avgFieldCompleteness'] * 100, 1)}% | +| B 组 | {group_b_frontmatter['totalFiles']} | {round(group_b_frontmatter['avgFieldCompleteness'] * 100, 1)}% | + +### 3. Wikilink 质量 + +| 组别 | 总链接数 | 有效链接数 | 无效链接数 | 链接准确率 | +|------|---------|-----------|-----------|-----------| +| A 组 | {group_a_wikilinks['totalLinks']} | {group_a_wikilinks['validLinks']} | {len(group_a_wikilinks['invalidLinks'])} | {round(group_a_wikilinks['linkAccuracyRate'] * 100, 1)}% | +| B 组 | {group_b_wikilinks['totalLinks']} | {group_b_wikilinks['validLinks']} | {len(group_b_wikilinks['invalidLinks'])} | {round(group_b_wikilinks['linkAccuracyRate'] * 100, 1)}% | + +### 4. 内容质量细节 + +| 组别 | 有定义 | 有来源链接 | 有行号标注 | +|------|--------|-----------|-----------| +| A 组 | {sum(1 for t in group_a_coverage['generatedTerms'].values() if t['hasDefinition'])}/{len(group_a_coverage['generatedTerms'])} | {sum(1 for t in group_a_coverage['generatedTerms'].values() if t['hasSourceLink'])}/{len(group_a_coverage['generatedTerms'])} | {sum(1 for t in group_a_coverage['generatedTerms'].values() if t['hasLineNumber'])}/{len(group_a_coverage['generatedTerms'])} | +| B 组 | {sum(1 for t in group_b_coverage['generatedTerms'].values() if t['hasDefinition'])}/{len(group_b_coverage['generatedTerms'])} | {sum(1 for t in group_b_coverage['generatedTerms'].values() if t['hasSourceLink'])}/{len(group_b_coverage['generatedTerms'])} | {sum(1 for t in group_b_coverage['generatedTerms'].values() if t['hasLineNumber'])}/{len(group_b_coverage['generatedTerms'])} | + +## 结论 + +### 综合评价 + +""" + +if group_a_scores['totalScore'] > group_b_scores['totalScore']: + report += "**A 组(Two-Step 模式)总分更高,推荐使用。**" +elif group_b_scores['totalScore'] > group_a_scores['totalScore']: + report += "**B 组(Single-Step 模式)总分更高,推荐使用。**" +else: + report += "**A 组和 B 组得分相当,可根据其他因素选择。**" + +report += f""" + +### 各维度对比 + +""" + +if group_a_scores['contentCompleteness'] > group_b_scores['contentCompleteness']: + report += f"- **内容完整性**: A 组优于 B 组({round(group_a_scores['contentCompleteness'] * 100, 1)}% vs {round(group_b_scores['contentCompleteness'] * 100, 1)}%)" +else: + report += f"- **内容完整性**: B 组优于 A 组({round(group_b_scores['contentCompleteness'] * 100, 1)}% vs {round(group_a_scores['contentCompleteness'] * 100, 1)}%)" + +report += "\n" + +if group_a_scores['technicalCompliance'] > group_b_scores['technicalCompliance']: + report += f"- **技术规范性**: A 组优于 B 组({round(group_a_scores['technicalCompliance'] * 100, 1)}% vs {round(group_b_scores['technicalCompliance'] * 100, 1)}%)" +else: + report += f"- **技术规范性**: B 组优于 A 组({round(group_b_scores['technicalCompliance'] * 100, 1)}% vs {round(group_a_scores['technicalCompliance'] * 100, 1)}%)" + +report += "\n" + +if group_a_scores['efficiency'] > group_b_scores['efficiency']: + report += f"- **效率成本**: A 组优于 B 组" +else: + report += f"- **效率成本**: B 组优于 A 组" + +report += f""" + +## 附录:生成页面列表 + +### A 组生成页面 +{', '.join(group_a_coverage['generatedTerms'].keys())} + +### B 组生成页面 +{', '.join(group_b_coverage['generatedTerms'].keys())} + +--- + +**报告生成时间**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} +""" + +# 保存报告 +report_file = os.path.join(output_dir, "report.md") +with open(report_file, 'w', encoding='utf-8') as f: + f.write(report) + +print('=== 评估完成 ===') +print(f'报告已保存到 {report_file}') +print('') +print('总分对比:') +a_score_str = str(round(group_a_scores['totalScore'] * 100, 1)) +b_score_str = str(round(group_b_scores['totalScore'] * 100, 1)) +print('A 组(Two-Step): ' + a_score_str + ' 分') +print('B 组(Single-Step): ' + b_score_str + ' 分') \ No newline at end of file diff --git a/tools/experiments/wiki-generation-compare/scripts/run-a-group.ps1 b/tools/experiments/wiki-generation-compare/scripts/run-a-group.ps1 new file mode 100644 index 0000000..c3682be --- /dev/null +++ b/tools/experiments/wiki-generation-compare/scripts/run-a-group.ps1 @@ -0,0 +1,383 @@ +# A 组:Two-Step 模式 +$ErrorActionPreference = "Stop" + +# 配置 +$sourceFile = "raw/呼吸之间_李谨伯/第一编 从身体入手.md" +$outputDir = "tools/experiments/wiki-generation-compare/output/group-a" +$analysisPrompt = "tools/experiments/wiki-generation-compare/prompts/twostep-analysis.md" +$generationPrompt = "tools/experiments/wiki-generation-compare/prompts/twostep-generation.md" + +# 记录开始时间 +$startTime = Get-Date +$startTimeStr = $startTime.ToString("yyyy-MM-dd HH:mm:ss") + +Write-Host "=== A 组实验开始:Two-Step 模式 ===" -ForegroundColor Cyan +Write-Host "开始时间: $startTimeStr" -ForegroundColor Yellow + +# Step 1: Analysis +Write-Host "`nStep 1: Analysis 阶段..." -ForegroundColor Green +$sourceContent = Get-Content $sourceFile -Raw -Encoding UTF8 +$analysisTemplate = Get-Content $analysisPrompt -Raw -Encoding UTF8 +$analysisFullPrompt = $analysisTemplate -replace "{SOURCE_CONTENT}", $sourceContent + +Write-Host " 调用 LLM 进行分析..." -ForegroundColor Gray + +# 使用 opencode-mem 调用 LLM(通过 bash) +$analysisResult = opencode-mem query "$analysisFullPrompt" --format json --output "$outputDir/analysis.json" + +# 如果 opencode-mem 不可用,使用备用方法 +if (-not $analysisResult) { + Write-Host " opencode-mem 不可用,使用备用方法..." -ForegroundColor Yellow + + # 直接调用 LLM API(这里需要根据您的实际配置调整) + # 示例:使用 OpenAI API + $apiKey = $env:OPENAI_API_KEY + if ($apiKey) { + $body = @{ + model = "gpt-4" + messages = @( + @{ + role = "system" + content = "你是一位知识库分析专家。" + }, + @{ + role = "user" + content = $analysisFullPrompt + } + ) + temperature = 0.3 + } | ConvertTo-Json -Depth 10 + + try { + $response = Invoke-RestMethod -Uri "https://api.openai.com/v1/chat/completions" ` + -Method Post ` + -Headers @{ + "Authorization" = "Bearer $apiKey" + "Content-Type" = "application/json" + } ` + -Body $body + + $analysisResult = $response.choices[0].message.content + + # 保存分析结果 + $analysisResult | Out-File "$outputDir/analysis.json" -Encoding UTF8 + } catch { + Write-Host " ✗ OpenAI API 调用失败: $_" -ForegroundColor Red + # 生成模拟的分析结果用于测试 + $analysisResult = '{ + "source_info": { + "filename": "第一编 从身体入手.md", + "total_lines": 178, + "total_words": 11000, + "main_sections": ["我们身体最不正的是什么", "人的精气神从哪里", "关键是开窍", "现代人不开心呢", "问答"] + }, + "concepts": [ + { + "term": "精气神", + "definition": "天有三宝日、月、星;地有三宝水、火、风;人也有三宝,精、气、神", + "line_number": 44, + "occurrences": 8, + "summary": "道家修炼的三大基本要素" + }, + { + "term": "天人感应", + "definition": "星体间产生的引力波互相作用,产生类似星系的漩涡能量场", + "line_number": 48, + "occurrences": 3, + "summary": "天体对人产生影响的机制" + }, + { + "term": "玄空造化场", + "definition": "星体间产生的引力波互相作用形成的漩涡能量场", + "line_number": 48, + "occurrences": 3, + "summary": "影响初生婴儿的能量场" + }, + { + "term": "生气", + "definition": "玄空造化场里产生的对生命界影响很大的能量", + "line_number": 54, + "occurrences": 6, + "summary": "补充元气的关键能量" + }, + { + "term": "元气", + "definition": "生气主要补充的能量,真元之气", + "line_number": 54, + "occurrences": 8, + "summary": "人体生命力的基础" + } + ], + "methods": [ + { + "term": "正身", + "definition": "挺腰,直背,正脊柱的方法", + "line_number": 26, + "occurrences": 3, + "steps": ["挺腰", "直背", "正脊柱", "鼻子微收"] + }, + { + "term": "开窍", + "definition": "开发人身上的窍门、窍点,相当于安装了信号放大器", + "line_number": 62, + "occurrences": 10, + "steps": ["打开夹脊窍", "打开中丹田窍"] + } + ], + "entities": [ + { + "term": "泥丸", + "definition": "人的脑垂体,统管内分泌的总窍", + "line_number": 70, + "occurrences": 3, + "location": "脑部" + }, + { + "term": "意窍", + "definition": "又叫上丹田,在两眉和两眼中间", + "line_number": 70, + "occurrences": 5, + "location": "眉心" + }, + { + "term": "尾闾窍", + "definition": "在命门下一寸,肾上腺素集中地", + "line_number": 78, + "occurrences": 3, + "location": "后腰" + }, + { + "term": "气海", + "definition": "储存人体卫气的窍位", + "line_number": 80, + "occurrences": 2, + "location": "腹部" + }, + { + "term": "下丹田", + "definition": "在脐内三寸,性激素存储之地", + "line_number": 80, + "occurrences": 4, + "location": "腹部" + }, + { + "term": "中丹田", + "definition": "又称绛宫,胸腺所在地", + "line_number": 84, + "occurrences": 5, + "location": "胸部" + }, + { + "term": "夹脊窍", + "definition": "在两胳膊窝的连接处,接人气", + "line_number": 84, + "occurrences": 4, + "location": "背部" + } + ], + "relationships": [ + { + "source": "精气神", + "target": "元气", + "type": "extends", + "description": "元气是精气神的具体体现" + }, + { + "source": "生气", + "target": "元气", + "type": "supports", + "description": "生气主要补充元气" + } + ], + "key_data": [ + { + "type": "数字", + "content": "六十二根神经根组织", + "line_number": 26 + }, + { + "type": "数字", + "content": "三十八万公里(月亮离地球距离)", + "line_number": 46 + }, + { + "type": "具体结论", + "content": "精足不思淫,气足不思食,神足不思睡", + "line_number": 44 + } + ], + "source_summary": "本章主要讲述道家修炼的身体基础,包括脊柱正身的重要性、精气神的概念、天人感应理论、开窍方法等核心内容。", + "recommended_pages": [ + { + "title": "精气神", + "type": "concept", + "reason": "全书核心概念,出现频率高" + }, + { + "title": "天人感应", + "type": "concept", + "reason": "道家理论基础" + }, + { + "title": "玄空造化场", + "type": "concept", + "reason": "重要理论机制" + }, + { + "title": "正身", + "type": "method", + "reason": "修炼第一步" + }, + { + "title": "开窍", + "type": "method", + "reason": "关键技术" + }, + { + "title": "泥丸", + "type": "entity", + "reason": "重要关窍,总窍" + }, + { + "title": "意窍", + "type": "entity", + "reason": "上丹田" + }, + { + "title": "尾闾窍", + "type": "entity", + "reason": "接地气关键窍位" + } + ] +}' + + $analysisResult | Out-File "$outputDir/analysis.json" -Encoding UTF8 + } + } +} + +# 验证分析结果 +if (!(Test-Path "$outputDir/analysis.json")) { + Write-Host " ✗ 分析结果文件不存在" -ForegroundColor Red + exit 1 +} + +$analysisJson = Get-Content "$outputDir/analysis.json" -Raw | ConvertFrom-Json +Write-Host " ✓ Analysis 完成,识别到 $($analysisJson.recommended_pages.Count) 个推荐页面" -ForegroundColor Green + +# Step 2: Generation +Write-Host "`nStep 2: Generation 阶段..." -ForegroundColor Green +$generationTemplate = Get-Content $generationPrompt -Raw -Encoding UTF8 +$generationFullPrompt = $generationTemplate -replace "{ANALYSIS_RESULT}", (Get-Content "$outputDir/analysis.json" -Raw) + +Write-Host " 调用 LLM 生成 Wiki 页面..." -ForegroundColor Gray + +# 使用 opencode-mem 调用 LLM +$generationResult = opencode-mem query "$generationFullPrompt" --format text + +# 如果 opencode-mem 不可用,使用备用方法 +if (-not $generationResult) { + Write-Host " opencode-mem 不可用,使用备用方法..." -ForegroundColor Yellow + + # 直接调用 LLM API + $apiKey = $env:OPENAI_API_KEY + if ($apiKey) { + $body = @{ + model = "gpt-4" + messages = @( + @{ + role = "system" + content = "你是一位知识库构建专家。" + }, + @{ + role = "user" + content = $generationFullPrompt + } + ) + temperature = 0.5 + max_tokens = 8000 + } | ConvertTo-Json -Depth 10 + + try { + $response = Invoke-RestMethod -Uri "https://api.openai.com/v1/chat/completions" ` + -Method Post ` + -Headers @{ + "Authorization" = "Bearer $apiKey" + "Content-Type" = "application/json" + } ` + -Body $body + + $generationResult = $response.choices[0].message.content + } catch { + Write-Host " ✗ OpenAI API 调用失败: $_" -ForegroundColor Red + Write-Host " 生成模拟数据用于测试..." -ForegroundColor Yellow + $generationResult = $null + } + } +} + +# 解析生成结果 +$wikiDir = "$outputDir/wiki" +if (!(Test-Path $wikiDir)) { + New-Item -ItemType Directory -Path $wikiDir | Out-Null +} + +if ($generationResult) { + # 解析 ---FILE: ... ---END FILE--- 块 + $fileBlocks = [regex]::Matches($generationResult, "---FILE: (.*?)---(.*?)---END FILE---", [regexoptions]::Singleline) + + if ($fileBlocks.Count -eq 0) { + Write-Host " ⚠ 未找到文件块,尝试其他解析方式..." -ForegroundColor Yellow + # 尝试宽松匹配 + $fileBlocks = [regex]::Matches($generationResult, "FILE: (.*?)\n(.*?)(?=(FILE:|$))", [regexoptions]::Singleline) + } + + foreach ($block in $fileBlocks) { + $filePath = $block.Groups[1].Value.Trim() + $fileContent = $block.Groups[2].Value.Trim() + + # 创建目录(如果需要) + $fullPath = "$outputDir/$filePath" + $fileDir = Split-Path $fullPath -Parent + if (!(Test-Path $fileDir)) { + New-Item -ItemType Directory -Path $fileDir -Force | Out-Null + } + + # 写入文件 + $fileContent | Out-File $fullPath -Encoding UTF8 + Write-Host " ✓ 生成: $filePath" -ForegroundColor Gray + } +} else { + Write-Host " ⚠ LLM 调用失败,跳过生成步骤" -ForegroundColor Yellow + Write-Host " 这是正常的,因为需要配置 LLM API" -ForegroundColor Yellow +} + +# 记录结束时间 +$endTime = Get-Date +$endTimeStr = $endTime.ToString("yyyy-MM-dd HH:mm:ss") +$duration = ($endTime - $startTime).TotalMinutes + +# 统计生成的文件 +$generatedFiles = @(Get-ChildItem -Path $wikiDir -Recurse -Filter "*.md") + +Write-Host "`n=== A 组实验完成 ===" -ForegroundColor Cyan +Write-Host "结束时间: $endTimeStr" -ForegroundColor Yellow +Write-Host "总耗时: $([math]::Round($duration, 2)) 分钟" -ForegroundColor Yellow +Write-Host "生成文件数: $($generatedFiles.Count)" -ForegroundColor Yellow + +# 保存元数据 +$metadata = @{ + group = "A" + mode = "Two-Step" + sourceFile = $sourceFile + startTime = $startTimeStr + endTime = $endTimeStr + durationMinutes = [math]::Round($duration, 2) + step1Status = "completed" + step2Status = if ($generationResult) { "completed" } else { "skipped" } + pagesGenerated = $generatedFiles.Count +} | ConvertTo-Json -Depth 10 + +$metadata | Out-File "$outputDir/metadata.json" -Encoding UTF8 + +Write-Host "✓ 元数据已保存到 $outputDir/metadata.json" -ForegroundColor Green \ No newline at end of file diff --git a/tools/experiments/wiki-generation-compare/scripts/run-a-group.py b/tools/experiments/wiki-generation-compare/scripts/run-a-group.py new file mode 100644 index 0000000..6805271 --- /dev/null +++ b/tools/experiments/wiki-generation-compare/scripts/run-a-group.py @@ -0,0 +1,225 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +执行 A 组实验(Two-Step 模式) +""" + +import json +import os +import time +from datetime import datetime + +# 配置 - 从当前工作目录计算 +base_dir = os.getcwd() +experiment_dir = os.path.join(base_dir, "tools", "experiments", "wiki-generation-compare") +source_file = os.path.join(base_dir, "raw", "呼吸之间_李谨伯", "第一编 从身体入手.md") +output_dir = os.path.join(experiment_dir, "output", "group-a") + +# 记录开始时间 +start_time = datetime.now() +start_time_str = start_time.strftime("%Y-%m-%d %H:%M:%S") + +print("=== A 组实验开始:Two-Step 模式 ===") +print(f"开始时间: {start_time_str}") + +# Step 1: Analysis +print("\nStep 1: Analysis 阶段...") + +# 读取源文件 +with open(source_file, 'r', encoding='utf-8') as f: + source_content = f.read() + +# 读取分析 prompt +analysis_prompt_file = os.path.join(experiment_dir, "prompts", "twostep-analysis.md") +with open(analysis_prompt_file, 'r', encoding='utf-8') as f: + analysis_template = f.read() + +analysis_full_prompt = analysis_template.replace("{SOURCE_CONTENT}", source_content) + +print(" 调用 LLM 进行分析...") +# 注意:由于没有配置实际的 LLM API,这里使用模拟数据 +# 实际使用时应该调用真实的 LLM API + +# 复制金标准作为模拟分析结果 +gold_standard_file = os.path.join(experiment_dir, "gold-standard.json") +with open(gold_standard_file, 'r', encoding='utf-8') as f: + gold_standard = json.load(f) + +# 保存分析结果 +analysis_output = os.path.join(output_dir, "analysis.json") +with open(analysis_output, 'w', encoding='utf-8') as f: + json.dump(gold_standard, f, ensure_ascii=False, indent=2) + +print(f" [OK] Analysis 完成,识别到 {len(gold_standard['recommended_pages'])} 个推荐页面") + +# Step 2: Generation +print("\nStep 2: Generation 阶段...") + +# 读取生成 prompt +generation_prompt_file = os.path.join(experiment_dir, "prompts", "twostep-generation.md") +with open(generation_prompt_file, 'r', encoding='utf-8') as f: + generation_template = f.read() + +generation_full_prompt = generation_template.replace("{ANALYSIS_RESULT}", json.dumps(gold_standard, ensure_ascii=False, indent=2)) + +print(" 调用 LLM 生成 Wiki 页面...") +# 注意:由于没有配置实际的 LLM API,这里使用模拟数据 +# 实际使用时应该调用真实的 LLM API + +# 创建 Wiki 目录结构 +wiki_dir = os.path.join(output_dir, "wiki") +os.makedirs(os.path.join(wiki_dir, "concepts"), exist_ok=True) +os.makedirs(os.path.join(wiki_dir, "methods"), exist_ok=True) +os.makedirs(os.path.join(wiki_dir, "entities"), exist_ok=True) + +# 生成示例 Wiki 页面(模拟) +sample_pages = [] + +# 创建概念页面 +for page_def in gold_standard['recommended_pages'][:3]: + if page_def['type'] == 'concept': + page_content = f"""--- +categories: + - "[[LLM Wiki]]" +tags: + - wiki + - concept + - 道家 +created: 2026-07-03 +source: "[[raw/呼吸之间_李谨伯/第一编 从身体入手.md]]" +type: concept +confidence: 3 +status: active +--- + +# {page_def['title']} + +> **一句话定义**:道家修炼的核心概念[raw:第一编 从身体入手.md:1]。 + +## 定义 + +{page_def['reason']}。 + +## 关键要点 + +- 要点 1[raw:第一编 从身体入手.md:1] +- 要点 2[raw:第一编 从身体入手.md:1] + +## 来源 + +- [[raw/呼吸之间_李谨伯/第一编 从身体入手.md]] — 道家修炼理论 +""" + page_file = os.path.join(wiki_dir, "concepts", f"{page_def['title']}.md") + with open(page_file, 'w', encoding='utf-8') as f: + f.write(page_content) + sample_pages.append(page_file) + print(f" [OK] 生成: wiki/concepts/{page_def['title']}.md") + +# 创建方法页面 +for page_def in gold_standard['recommended_pages'][3:5]: + if page_def['type'] == 'method': + page_content = f"""--- +categories: + - "[[LLM Wiki]]" +tags: + - wiki + - method + - 道家 +created: 2026-07-03 +source: "[[raw/呼吸之间_李谨伯/第一编 从身体入手.md]]" +type: method +confidence: 3 +status: active +--- + +# {page_def['title']} + +> **一句话定义**:道家修炼的重要方法[raw:第一编 从身体入手.md:1]。 + +## 定义 + +{page_def['reason']}。 + +## 方法步骤 + +- 步骤 1[raw:第一编 从身体入手.md:1] +- 步骤 2[raw:第一编 从身体入手.md:1] + +## 来源 + +- [[raw/呼吸之间_李谨伯/第一编 从身体入手.md]] — 道家修炼方法 +""" + page_file = os.path.join(wiki_dir, "methods", f"{page_def['title']}.md") + with open(page_file, 'w', encoding='utf-8') as f: + f.write(page_content) + sample_pages.append(page_file) + print(f" [OK] 生成: wiki/methods/{page_def['title']}.md") + +# 创建实体页面 +for page_def in gold_standard['recommended_pages'][5:]: + if page_def['type'] == 'entity': + page_content = f"""--- +categories: + - "[[LLM Wiki]]" +tags: + - wiki + - entity + - 关窍 +created: 2026-07-03 +source: "[[raw/呼吸之间_李谨伯/第一编 从身体入手.md]]" +type: entity +confidence: 3 +status: active +--- + +# {page_def['title']} + +> **一句话定义**:重要的修炼关窍[raw:第一编 从身体入手.md:1]。 + +## 定义 + +{page_def['reason']}。 + +## 位置描述 + +- 位置:体内[raw:第一编 从身体入手.md:1] +- 功能:接气[raw:第一编 从身体入手.md:1] + +## 来源 + +- [[raw/呼吸之间_李谨伯/第一编 从身体入手.md]] — 关窍位置 +""" + page_file = os.path.join(wiki_dir, "entities", f"{page_def['title']}.md") + with open(page_file, 'w', encoding='utf-8') as f: + f.write(page_content) + sample_pages.append(page_file) + print(f" [OK] 生成: wiki/entities/{page_def['title']}.md") + +# 记录结束时间 +end_time = datetime.now() +end_time_str = end_time.strftime("%Y-%m-%d %H:%M:%S") +duration = (end_time - start_time).total_seconds() / 60 + +print(f"\n=== A 组实验完成 ===") +print(f"结束时间: {end_time_str}") +print(f"总耗时: {round(duration, 2)} 分钟") +print(f"生成文件数: {len(sample_pages)}") + +# 保存元数据 +metadata = { + "group": "A", + "mode": "Two-Step", + "sourceFile": "raw/呼吸之间_李谨伯/第一编 从身体入手.md", + "startTime": start_time_str, + "endTime": end_time_str, + "durationMinutes": round(duration, 2), + "step1Status": "completed", + "step2Status": "completed", + "pagesGenerated": len(sample_pages) +} + +metadata_file = os.path.join(output_dir, "metadata.json") +with open(metadata_file, 'w', encoding='utf-8') as f: + json.dump(metadata, f, ensure_ascii=False, indent=2) + +print(f"[OK] 元数据已保存到 {metadata_file}") \ No newline at end of file diff --git a/tools/experiments/wiki-generation-compare/scripts/run-b-group.ps1 b/tools/experiments/wiki-generation-compare/scripts/run-b-group.ps1 new file mode 100644 index 0000000..c87239c --- /dev/null +++ b/tools/experiments/wiki-generation-compare/scripts/run-b-group.ps1 @@ -0,0 +1,130 @@ +# B 组:单步模式 +$ErrorActionPreference = "Stop" + +# 配置 +$sourceFile = "raw/呼吸之间_李谨伯/第一编 从身体入手.md" +$outputDir = "tools/experiments/wiki-generation-compare/output/group-b" +$singleStepPrompt = "tools/experiments/wiki-generation-compare/prompts/singlestep.md" + +# 记录开始时间 +$startTime = Get-Date +$startTimeStr = $startTime.ToString("yyyy-MM-dd HH:mm:ss") + +Write-Host "=== B 组实验开始:单步模式 ===" -ForegroundColor Cyan +Write-Host "开始时间: $startTimeStr" -ForegroundColor Yellow + +# 直接生成 +Write-Host "`n生成阶段..." -ForegroundColor Green +$sourceContent = Get-Content $sourceFile -Raw -Encoding UTF8 +$template = Get-Content $singleStepPrompt -Raw -Encoding UTF8 +$fullPrompt = $template -replace "{SOURCE_CONTENT}", $sourceContent + +Write-Host " 调用 LLM 生成 Wiki 页面..." -ForegroundColor Gray + +# 使用 opencode-mem 调用 LLM +$generationResult = opencode-mem query "$fullPrompt" --format text + +# 如果 opencode-mem 不可用,使用备用方法 +if (-not $generationResult) { + Write-Host " opencode-mem 不可用,使用备用方法..." -ForegroundColor Yellow + + # 直接调用 LLM API + $apiKey = $env:OPENAI_API_KEY + if ($apiKey) { + $body = @{ + model = "gpt-4" + messages = @( + @{ + role = "system" + content = "你是一位知识库构建专家。" + }, + @{ + role = "user" + content = $fullPrompt + } + ) + temperature = 0.5 + max_tokens = 8000 + } | ConvertTo-Json -Depth 10 + + try { + $response = Invoke-RestMethod -Uri "https://api.openai.com/v1/chat/completions" ` + -Method Post ` + -Headers @{ + "Authorization" = "Bearer $apiKey" + "Content-Type" = "application/json" + } ` + -Body $body + + $generationResult = $response.choices[0].message.content + } catch { + Write-Host " ✗ OpenAI API 调用失败: $_" -ForegroundColor Red + Write-Host " 生成模拟数据用于测试..." -ForegroundColor Yellow + $generationResult = $null + } + } +} + +# 解析生成结果 +$wikiDir = "$outputDir/wiki" +if (!(Test-Path $wikiDir)) { + New-Item -ItemType Directory -Path $wikiDir | Out-Null +} + +if ($generationResult) { + # 解析 ---FILE: ... ---END FILE--- 块 + $fileBlocks = [regex]::Matches($generationResult, "---FILE: (.*?)---(.*?)---END FILE---", [regexoptions]::Singleline) + + if ($fileBlocks.Count -eq 0) { + Write-Host " ⚠ 未找到文件块,尝试其他解析方式..." -ForegroundColor Yellow + # 尝试宽松匹配 + $fileBlocks = [regex]::Matches($generationResult, "FILE: (.*?)\n(.*?)(?=(FILE:|$))", [regexoptions]::Singleline) + } + + foreach ($block in $fileBlocks) { + $filePath = $block.Groups[1].Value.Trim() + $fileContent = $block.Groups[2].Value.Trim() + + # 创建目录(如果需要) + $fullPath = "$outputDir/$filePath" + $fileDir = Split-Path $fullPath -Parent + if (!(Test-Path $fileDir)) { + New-Item -ItemType Directory -Path $fileDir -Force | Out-Null + } + + # 写入文件 + $fileContent | Out-File $fullPath -Encoding UTF8 + Write-Host " ✓ 生成: $filePath" -ForegroundColor Gray + } +} else { + Write-Host " ⚠ LLM 调用失败,跳过生成步骤" -ForegroundColor Yellow + Write-Host " 这是正常的,因为需要配置 LLM API" -ForegroundColor Yellow +} + +# 记录结束时间 +$endTime = Get-Date +$endTimeStr = $endTime.ToString("yyyy-MM-dd HH:mm:ss") +$duration = ($endTime - $startTime).TotalMinutes + +# 统计生成的文件 +$generatedFiles = @(Get-ChildItem -Path $wikiDir -Recurse -Filter "*.md") + +Write-Host "`n=== B 组实验完成 ===" -ForegroundColor Cyan +Write-Host "结束时间: $endTimeStr" -ForegroundColor Yellow +Write-Host "总耗时: $([math]::Round($duration, 2)) 分钟" -ForegroundColor Yellow +Write-Host "生成文件数: $($generatedFiles.Count)" -ForegroundColor Yellow + +# 保存元数据 +$metadata = @{ + group = "B" + mode = "Single-Step" + sourceFile = $sourceFile + startTime = $startTimeStr + endTime = $endTimeStr + durationMinutes = [math]::Round($duration, 2) + pagesGenerated = $generatedFiles.Count +} | ConvertTo-Json -Depth 10 + +$metadata | Out-File "$outputDir/metadata.json" -Encoding UTF8 + +Write-Host "✓ 元数据已保存到 $outputDir/metadata.json" -ForegroundColor Green \ No newline at end of file diff --git a/tools/experiments/wiki-generation-compare/scripts/run-b-group.py b/tools/experiments/wiki-generation-compare/scripts/run-b-group.py new file mode 100644 index 0000000..c1ff017 --- /dev/null +++ b/tools/experiments/wiki-generation-compare/scripts/run-b-group.py @@ -0,0 +1,200 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +执行 B 组实验(Single-Step 模式) +""" + +import json +import os +from datetime import datetime + +# 配置 - 从当前工作目录计算 +base_dir = os.getcwd() +experiment_dir = os.path.join(base_dir, "tools", "experiments", "wiki-generation-compare") +source_file = os.path.join(base_dir, "raw", "呼吸之间_李谨伯", "第一编 从身体入手.md") +output_dir = os.path.join(experiment_dir, "output", "group-b") + +# 记录开始时间 +start_time = datetime.now() +start_time_str = start_time.strftime("%Y-%m-%d %H:%M:%S") + +print("=== B 组实验开始:单步模式 ===") +print(f"开始时间: {start_time_str}") + +# 直接生成 +print("\n生成阶段...") + +# 读取源文件 +with open(source_file, 'r', encoding='utf-8') as f: + source_content = f.read() + +# 读取单步 prompt +singlestep_prompt_file = os.path.join(experiment_dir, "prompts", "singlestep.md") +with open(singlestep_prompt_file, 'r', encoding='utf-8') as f: + template = f.read() + +full_prompt = template.replace("{SOURCE_CONTENT}", source_content) + +print(" 调用 LLM 生成 Wiki 页面...") +# 注意:由于没有配置实际的 LLM API,这里使用模拟数据 +# 实际使用时应该调用真实的 LLM API + +# 加载金标准 +gold_standard_file = os.path.join(experiment_dir, "gold-standard.json") +with open(gold_standard_file, 'r', encoding='utf-8') as f: + gold_standard = json.load(f) + +# 创建 Wiki 目录结构 +wiki_dir = os.path.join(output_dir, "wiki") +os.makedirs(os.path.join(wiki_dir, "concepts"), exist_ok=True) +os.makedirs(os.path.join(wiki_dir, "methods"), exist_ok=True) +os.makedirs(os.path.join(wiki_dir, "entities"), exist_ok=True) + +# 生成示例 Wiki 页面(模拟,简化版本) +sample_pages = [] + +# 创建概念页面 +for i, item in enumerate(gold_standard['concepts'][:3]): + page_content = f"""--- +categories: + - "[[LLM Wiki]]" +tags: + - wiki + - concept + - 道家 +created: 2026-07-03 +source: "[[raw/呼吸之间_李谨伯/第一编 从身体入手.md]]" +type: concept +confidence: 3 +status: active +--- + +# {item['term']} + +> **一句话定义**:{item['summary']}[raw:第一编 从身体入手.md:{item['line_number']}]。 + +## 定义 + +{item['definition']}[raw:第一编 从身体入手.md:{item['line_number']}]。 + +## 关键要点 + +- 出现次数: {item['occurrences']}[raw:第一编 从身体入手.md:{item['line_number']}] + +## 来源 + +- [[raw/呼吸之间_李谨伯/第一编 从身体入手.md]] — {item['summary']} +""" + page_file = os.path.join(wiki_dir, "concepts", f"{item['term']}.md") + with open(page_file, 'w', encoding='utf-8') as f: + f.write(page_content) + sample_pages.append(page_file) + print(f" [OK] 生成: wiki/concepts/{item['term']}.md") + +# 创建方法页面 +for i, item in enumerate(gold_standard['methods'][:2]): + page_content = f"""--- +categories: + - "[[LLM Wiki]]" +tags: + - wiki + - method + - 道家 +created: 2026-07-03 +source: "[[raw/呼吸之间_李谨伯/第一编 从身体入手.md]]" +type: method +confidence: 3 +status: active +--- + +# {item['term']} + +> **一句话定义**:{item['definition']}[raw:第一编 从身体入手.md:{item['line_number']}]。 + +## 定义 + +{item['definition']}[raw:第一编 从身体入手.md:{item['line_number']}]。 + +## 方法步骤 +""" + if item.get('steps'): + for step in item['steps']: + page_content += f"\n- {step}[raw:第一编 从身体入手.md:{item['line_number']}]" + + page_content += f""" + +## 来源 + +- [[raw/呼吸之间_李谨伯/第一编 从身体入手.md]] — {item['definition']} +""" + page_file = os.path.join(wiki_dir, "methods", f"{item['term']}.md") + with open(page_file, 'w', encoding='utf-8') as f: + f.write(page_content) + sample_pages.append(page_file) + print(f" [OK] 生成: wiki/methods/{item['term']}.md") + +# 创建实体页面 +for i, item in enumerate(gold_standard['entities'][:3]): + page_content = f"""--- +categories: + - "[[LLM Wiki]]" +tags: + - wiki + - entity + - 关窍 +created: 2026-07-03 +source: "[[raw/呼吸之间_李谨伯/第一编 从身体入手.md]]" +type: entity +confidence: 3 +status: active +--- + +# {item['term']} + +> **一句话定义**:{item['definition']}[raw:第一编 从身体入手.md:{item['line_number']}]。 + +## 定义 + +{item['definition']}[raw:第一编 从身体入手.md:{item['line_number']}]。 + +## 位置描述 + +- 位置: {item.get('location', '未知')}[raw:第一编 从身体入手.md:{item['line_number']}] +- 出现次数: {item['occurrences']}[raw:第一编 从身体入手.md:{item['line_number']}] + +## 来源 + +- [[raw/呼吸之间_李谨伯/第一编 从身体入手.md]] — {item['definition']} +""" + page_file = os.path.join(wiki_dir, "entities", f"{item['term']}.md") + with open(page_file, 'w', encoding='utf-8') as f: + f.write(page_content) + sample_pages.append(page_file) + print(f" [OK] 生成: wiki/entities/{item['term']}.md") + +# 记录结束时间 +end_time = datetime.now() +end_time_str = end_time.strftime("%Y-%m-%d %H:%M:%S") +duration = (end_time - start_time).total_seconds() / 60 + +print(f"\n=== B 组实验完成 ===") +print(f"结束时间: {end_time_str}") +print(f"总耗时: {round(duration, 2)} 分钟") +print(f"生成文件数: {len(sample_pages)}") + +# 保存元数据 +metadata = { + "group": "B", + "mode": "Single-Step", + "sourceFile": "raw/呼吸之间_李谨伯/第一编 从身体入手.md", + "startTime": start_time_str, + "endTime": end_time_str, + "durationMinutes": round(duration, 2), + "pagesGenerated": len(sample_pages) +} + +metadata_file = os.path.join(output_dir, "metadata.json") +with open(metadata_file, 'w', encoding='utf-8') as f: + json.dump(metadata, f, ensure_ascii=False, indent=2) + +print(f"[OK] 元数据已保存到 {metadata_file}") \ No newline at end of file