Files
llm_wiki/tools/experiments/wiki-generation-compare/scripts/run-a-group.ps1
T

383 lines
12 KiB
PowerShell
Raw Blame History

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