Skip to content

实施指南

前置准备

系统要求检查

在开始实施之前,请确保系统满足以下要求:

必需依赖

bash
# 检查 Bash 版本(需要 4.0+)
bash --version
# 预期输出: GNU bash, version 4.0 或更高

# 检查 Git
git --version

# 检查 OpenCode
opencode --version

# 检查 jq(JSON 处理)
jq --version

# 检查 tmux(用于监控,可选)
tmux -V

安装缺失依赖

bash
# Ubuntu/Debian
sudo apt-get update
sudo apt-get install -y bash git jq tmux

# macOS
brew install bash git jq tmux

OpenCode GLM4.7 配置

bash
# 配置 OpenCode 使用 GLM4.7
opencode config set model glm-4-flash
opencode config set api-key YOUR_GLM_API_KEY

# 验证配置
opencode config list

环境变量设置

bash
# 添加到 ~/.bashrc 或 ~/.zshrc
export RALPH_MAX_ITERATIONS=50
export RALPH_MAX_API_CALLS=100
export RALPH_SESSION_TIMEOUT=86400  # 24小时
export RALPH_LOG_LEVEL=INFO

# 重新加载配置
source ~/.bashrc

方案 A:原生集成实施步骤

步骤 1:下载并适配 Ralph

bash
# 1. 克隆 Ralph 仓库
cd ~
git clone https://github.com/frankbria/ralph-claude-code.git
cd ralph-claude-code

# 2. 创建适配分支(可选)
git checkout -b opencode-adaptation

# 3. 备份原始文件
cp ralph_loop.sh ralph_loop.sh.original
cp ralph_import.sh ralph_import.sh.original

步骤 2:修改 Ralph 配置

修改 ralph_loop.sh

bash
# 找到 build_claude_command() 函数并修改

# 原始代码(大约在 200 行左右)
build_claude_command() {
    local prompt="$1"
    local output_format="$2"

    local cmd="claude"
    cmd="$cmd --continue"
    cmd="$cmd -p \"$prompt\""

    if [ "$output_format" = "json" ]; then
        cmd="$cmd --output-format json"
    fi

    echo "$cmd"
}

# 修改为
build_claude_command() {
    local prompt="$1"
    local output_format="$2"

    local cmd="opencode"
    cmd="$cmd --continue-session"
    cmd="$cmd -p \"$prompt\""

    if [ "$output_format" = "json" ]; then
        cmd="$cmd --json-output"
    fi

    echo "$cmd"
}

修改 install.sh(如果需要)

bash
# 找到 install_global_commands() 函数

# 确保安装路径正确
BIN_DIR="$HOME/.local/bin"
mkdir -p "$BIN_DIR"

# 复制脚本到全局路径
cp ralph_loop.sh "$BIN_DIR/ralph"
chmod +x "$BIN_DIR/ralph"

cp ralph_monitor.sh "$BIN_DIR/ralph-monitor"
chmod +x "$BIN_DIR/ralph-monitor"

步骤 3:创建 Stop Hook 钩子

bash
# 在项目中创建 hooks 目录
mkdir -p hooks

# 创建 stop-hook.sh
cat > hooks/stop-hook.sh << 'EOF'
#!/bin/bash

set -euo pipefail

# OpenCode Stop Hook - 适配版
# 用于拦截退出并决定是否继续循环

# 配置
MIN_COMPLETION_INDICATORS=2
DEBUG=false

# 日志函数
log() {
    if [ "$DEBUG" = "true" ]; then
        echo "[DEBUG] $@" >&2
    fi
}

# 主逻辑
main() {
    local output_file="$1"
    log "Stop Hook triggered for: $output_file"

    # 检查输出文件是否存在
    if [ ! -f "$output_file" ]; then
        log "Output file not found: $output_file"
        exit 0  # 允许退出
    fi

    # 提取完成指示器
    local completion_indicators=0
    local output_content=$(cat "$output_file")

    # 检查完成相关关键词
    completion_indicators+=$(echo "$output_content" | grep -oEi "complete|done|finished|ready|implemented|completed" | wc -l)
    log "Completion indicators: $completion_indicators"

    # 检查 EXIT_SIGNAL
    local exit_signal="false"
    if echo "$output_content" | grep -q "EXIT_SIGNAL.*true"; then
        exit_signal="true"
    fi
    log "EXIT_SIGNAL: $exit_signal"

    # 检查显式完成标记
    local explicit_complete=false
    if echo "$output_content" | grep -q "<<COMPLETED>>" || echo "$output_content" | grep -q "任务完成"; then
        explicit_complete=true
    fi
    log "Explicit complete: $explicit_complete"

    # 双重条件判断
    if [ $completion_indicators -ge $MIN_COMPLETION_INDICATORS ] && [ "$exit_signal" = "true" ]; then
        log "✅ Completion conditions met, allowing exit"
        exit 0  # 允许退出
    elif [ "$explicit_complete" = "true" ]; then
        log "✅ Explicit completion marker found, allowing exit"
        exit 0  # 允许退出
    else
        log "❌ Completion conditions not met, blocking exit"
        exit 2  # 阻止退出,触发下一轮循环
    fi
}

main "$@"
EOF

# 添加执行权限
chmod +x hooks/stop-hook.sh

步骤 4:初始化研究项目

bash
# 1. 使用 Ralph 设置项目
ralph-setup research-report-generator

# 2. 进入项目目录
cd research-report-generator

# 3. 项目结构应如下:
# research-report-generator/
# ├── PROMPT.md
# ├── @fix_plan.md
# ├── @AGENT.md
# ├── specs/
# ├── src/
# ├── examples/
# ├── logs/
# ├── docs/generated/
# └── hooks/
#     └── stop-hook.sh

步骤 5:配置研究项目

编辑 PROMPT.md

bash
cat > PROMPT.md << 'EOF'
# 自动化研究报告生成任务

## 项目目标

生成一份关于「人工智能在医疗诊断中的应用」的专业研究报告,字数约 15000-20000 字。

## 报告结构要求

研究报告必须包含以下章节:

1. **研究背景与意义**
   - 医疗诊断的现状与挑战
   - AI 技术的发展历程
   - 研究价值与意义

2. **文献综述**
   - 国内外研究现状
   - 主要技术流派分析
   - 存在的问题与不足

3. **技术方法论**
   - 机器学习算法在诊断中的应用
   - 深度学习模型分析
   - 多模态诊断技术

4. **案例分析**
   - 影像诊断(CT、MRI、X光)
   - 病理诊断
   - 实验室诊断

5. **挑战与限制**
   - 数据隐私与安全
   - 模型可解释性
   - 临床应用的伦理问题

6. **未来发展趋势**
   - 技术发展方向
   - 临床应用前景
   - 政策法规展望

7. **结论与建议**
   - 研究总结
   - 实践建议
   - 未来研究方向

## 质量要求

- 学术规范:使用 APA 格式引用文献
- 数据支撑:所有观点需有可靠来源
- 案例丰富:至少包含 5 个实际应用案例
- 图文并茂:包含必要的图表和示意图

## 完成标准

当满足以下所有条件时,在响应末尾输出 <<COMPLETED>> 标记:
- [ ] 所有 7 个章节完整撰写
- [ ] 字数在 15000-20000 字之间
- [ ] 文献引用不少于 30 篇
- [ ] 包含至少 5 个实际案例
- [ ] 格式规范,无语法错误
- [ ] 包含必要的图表
EOF

编辑 @fix_plan.md

bash
cat > @fix_plan.md << 'EOF'
# 任务优先级列表

## 高优先级任务(P0)

- [ ] 创建研究报告目录结构
- [ ] 撰写「研究背景与意义」章节(约 2000 字)
- [ ] 撰写「技术方法论」章节(约 3000 字)

## 中优先级任务(P1)

- [ ] 撰写「文献综述」章节(约 3000 字)
- [ ] 撰写「案例分析」章节(约 3500 字)
- [ ] 撰写「挑战与限制」章节(约 2000 字)

## 低优先级任务(P2)

- [ ] 撰写「未来发展趋势」章节(约 2000 字)
- [ ] 撰写「结论与建议」章节(约 1500 字)
- [ ] 添加必要的图表和示意图
- [ ] 完善文献引用(不少于 30 篇)
- [ ] 格式校对与排版优化
- [ ] 最终审查与质量检查
EOF

编辑 @AGENT.md

bash
cat > @AGENT.md << 'EOF'
# 构建和运行说明

## 开发环境

- AI 助手:OpenCode + GLM4.7
- 编程语言:Markdown
- 版本控制:Git

## 工作流程

1. 阅读 PROMPT.md 了解项目需求
2. 参考 @fix_plan.md 按优先级执行任务
3. 每完成一个任务,在 @fix_plan.md 中标记为 [x]
4. 定期提交 Git commit 保存进度

## 输出规范

- 所有研究报告内容输出到 src/ 目录
- 使用 Markdown 格式
- 文件命名规范: `01-章节名.md`, `02-章节名.md`
- 在每个章节末尾更新进度状态

## 进度跟踪

在每个迭代结束时,在响应末尾添加:

RALPH_STATUS: { "progress": 0-100, "current_task": "当前正在进行的任务", "completed_tasks": ["已完成的任务1", "已完成的任务2"], "pending_tasks": ["待办任务1", "待办任务2"], "EXIT_SIGNAL": false, "notes": "当前进展说明" }


## 完成条件

当所有 P0-P2 任务完成且满足 PROMPT.md 中的质量要求时,设置 EXIT_SIGNAL: true。
EOF

步骤 6:启动自动化循环

bash
# 方式 1:带 tmux 监控启动(推荐)
ralph --monitor

# 方式 2:手动启动两个终端
# 终端 1
ralph --verbose

# 终端 2
ralph-monitor

# 方式 3:后台运行
nohup ralph > logs/ralph.stdout 2> logs/ralph.stderr &
echo $! > logs/ralph.pid
ralph-monitor

步骤 7:监控与调试

查看实时状态

bash
# 使用 ralph-monitor
ralph-monitor

# 或手动查看日志
tail -f logs/ralph.log

# 查看 JSON 状态
cat status.json | jq '.'

常用调试命令

bash
# 检查循环状态
ralph --status

# 重置断路器
ralph --reset-circuit

# 查看断路器状态
ralph --circuit-status

# 检查会话状态
cat .ralph_session
cat .ralph_session_history

# 查看 API 调用统计
grep "API call" logs/ralph.log | wc -l

处理中断

bash
# 如果循环被中断,恢复执行
cd research-report-generator
ralph  # 会自动恢复上次的状态

# 如果需要从特定循环恢复
ralph --continue

# 重置会话(清除上下文)
ralph --reset-session

方案 B:外部循环实施步骤

步骤 1:创建项目结构

bash
# 1. 创建项目目录
mkdir research-project-external
cd research-project-external

# 2. 创建子目录
mkdir -p outputs logs src hooks

# 3. 创建必要的文件
touch .current_status.json
touch .loop_count
touch .api_calls

步骤 2:编写核心脚本

创建 ralph-external-loop.sh

bash
cat > ralph-external-loop.sh << 'EOF'
#!/bin/bash
set -euo pipefail

# Ralph 外部循环控制器 - OpenCode + GLM4.7
# 不依赖 Stop Hook,使用外部 Bash 循环实现

# 配置参数
MAX_ITERATIONS=50
MAX_API_CALLS=100
HOURLY_LIMIT_DURATION=3600  # 1小时
LOOP_DELAY=5  # 循环间隔秒数

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

# 初始化
init() {
    echo -e "${GREEN}初始化 Ralph 外部循环...${NC}"

    if [ ! -f .loop_count ]; then
        echo 0 > .loop_count
    fi

    if [ ! -f .api_calls ]; then
        echo 0 > .api_calls
    fi

    if [ ! -f .hour_limit_reset ]; then
        date +%s > .hour_limit_reset
    fi

    # 初始化状态文件
    if [ ! -f .current_status.json ]; then
        cat > .current_status.json << 'INIT'
{
  "loop_count": 0,
  "progress": 0,
  "current_task": "初始化项目",
  "completed_tasks": [],
  "pending_tasks": [
    "创建报告目录结构",
    "撰写研究背景章节",
    "文献检索与分析",
    "撰写方法论述",
    "数据分析与可视化",
    "撰写结论与建议",
    "格式校对与排版"
  ],
  "last_update": "",
  "api_calls_this_hour": 0,
  "no_progress_count": 0
}
INIT
    fi

    echo "✅ 初始化完成"
}

# 读取当前状态
read_status() {
    if [ -f .current_status.json ]; then
        cat .current_status.json
    else
        echo '{}'
    fi
}

# 更新状态
update_status() {
    local status="$1"
    echo "$status" > .current_status.json
}

# 生成上下文提示词
generate_prompt() {
    local status="$1"

    local loop_count=$(echo "$status" | jq -r '.loop_count // 0')
    local progress=$(echo "$status" | jq -r '.progress // 0')
    local current_task=$(echo "$status" | jq -r '.current_task // ""')
    local completed_tasks=$(echo "$status" | jq -r '.completed_tasks // []')
    local pending_tasks=$(echo "$status" | jq -r '.pending_tasks // []')

    cat << PROMPT
# 自动化研究报告生成 - 第 $((loop_count + 1)) 次迭代

## 📊 当前状态
- 进度: ${progress}%
- 循环次数: $loop_count

## ✅ 已完成任务
$(if [ "$completed_tasks" != "[]" ]; then
    echo "$completed_tasks" | jq -r '.[]' | sed 's/^/  - /'
  else
    echo "  (无)"
fi)

## ⏳ 待办任务
$(if [ "$pending_tasks" != "[]" ]; then
    echo "$pending_tasks" | jq -r '.[]' | head -5 | sed 's/^/  - /'
  else
    echo "  (无)"
fi)

## 📝 本次任务

$current_task

## 📋 原始需求

$(cat PROMPT.md)

---

### 指令

1. 执行当前任务
2. 完成后在响应末尾使用以下格式报告进展:

\`\`\`
RALPH_UPDATE:
{
  "completed_task": "完成的任务名称",
  "next_task": "建议的下一个任务",
  "progress": 新的进度百分比
}
\`\`\`

3. 如果所有任务完成,在最后添加: <<COMPLETED>>

请开始执行任务。
PROMPT
}

# 检查完成状态
check_completion() {
    local output="$1"

    if echo "$output" | grep -q "<<COMPLETED>>"; then
        return 0  # 完成
    fi

    return 1  # 未完成
}

# 解析输出并更新状态
parse_and_update_status() {
    local output="$1"
    local current_status="$2"

    local completed_task=$(echo "$output" | grep -oP '(?<=RALPH_UPDATE:).*' | jq -r '.completed_task // ""')
    local next_task=$(echo "$output" | grep -oP '(?<=RALPH_UPDATE:).*' | jq -r '.next_task // ""')
    local new_progress=$(echo "$output" | grep -oP '(?<=RALPH_UPDATE:).*' | jq -r '.progress // 0')

    local updated_status="$current_status"

    if [ -n "$completed_task" ]; then
        updated_status=$(echo "$updated_status" | \
            jq --arg ct "$completed_task" '.completed_tasks += [$ct]')
    fi

    if [ -n "$next_task" ]; then
        updated_status=$(echo "$updated_status" | \
            jq --arg nt "$next_task" '.current_task = $nt')
    fi

    updated_status=$(echo "$updated_status" | \
        jq --argjson lp "$new_progress" '.progress = $lp')

    echo "$updated_status"
}

# 主循环
main_loop() {
    init

    echo -e "${YELLOW}开始自动化循环...${NC}"
    echo ""

    while true; do
        # 读取循环计数
        local loop_count=$(cat .loop_count)

        # 检查最大循环次数
        if [ "$loop_count" -ge "$MAX_ITERATIONS" ]; then
            echo -e "${RED}达到最大循环次数 ($MAX_ITERATIONS),退出${NC}"
            break
        fi

        # 读取当前状态
        local current_status=$(read_status)

        # 生成提示词
        local prompt=$(generate_prompt "$current_status")

        # 执行 OpenCode
        echo -e "${GREEN}[循环 $((loop_count + 1))/$MAX_ITERATIONS] 正在执行...${NC}"
        local output=$(opencode -p "$prompt" 2>&1)

        # 保存输出
        echo "$output" > "outputs/loop_$(printf '%04d' $loop_count).txt"

        # 更新 API 调用计数
        local api_calls=$(cat .api_calls)
        ((api_calls++))
        echo "$api_calls" > .api_calls

        # 解析并更新状态
        local updated_status=$(parse_and_update_status "$output" "$current_status")
        update_status "$updated_status"

        # 检查完成
        if check_completion "$output"; then
            echo -e "${GREEN}✅ 任务完成!${NC}"
            break
        fi

        # 更新循环计数
        ((loop_count++))
        echo "$loop_count" > .loop_count

        # 等待
        echo "等待 $LOOP_DELAY 秒..."
        sleep "$LOOP_DELAY"
        echo ""
    done

    echo -e "${GREEN}循环结束,总迭代次数: $loop_count${NC}"
    echo "最终状态:"
    cat .current_status.json | jq '.'
}

# 主函数
main() {
    main_loop
}

main "$@"
EOF

chmod +x ralph-external-loop.sh

创建 monitor.sh

bash
cat > monitor.sh << 'EOF'
#!/bin/bash
set -euo pipefail

# Ralph 外部循环监控面板

clear_monitor() {
    clear
    echo "═══════════════════════════════════════════════════"
    echo "     Ralph 外部循环 - 实时监控面板"
    echo "═══════════════════════════════════════════════════"
    echo ""
}

display_status() {
    if [ ! -f .current_status.json ]; then
        echo "⚠️  状态文件不存在"
        return
    fi

    local status=$(cat .current_status.json)

    echo "📊 当前进度: $(echo "$status" | jq -r '.progress // 0')%"
    echo "🔄 迭代次数: $(echo "$status" | jq -r '.loop_count // 0')"
    echo "📝 当前任务: $(echo "$status" | jq -r '.current_task // "无"')"
    echo ""

    echo "✅ 已完成任务:"
    local completed=$(echo "$status" | jq -r '.completed_tasks // []')
    if [ "$completed" = "[]" ]; then
        echo "   (无)"
    else
        echo "$completed" | jq -r '.[]' | sed 's/^/   - /'
    fi

    echo ""
    echo "⏳ 待办任务:"
    local pending=$(echo "$status" | jq -r '.pending_tasks // []')
    if [ "$pending" = "[]" ]; then
        echo "   (无)"
    else
        echo "$pending" | jq -r '.[]' | head -5 | sed 's/^/   - /'
    fi

    echo ""
    echo "📞 API 调用: $(cat .api_calls 2>/dev/null || echo 0)/100 (每小时)"
    echo "⏰ 最后更新: $(echo "$status" | jq -r '.last_update // "无"')"
}

main() {
    while [ -f .current_status.json ] || [ -f .loop_count ]; do
        clear_monitor
        display_status
        echo ""
        echo "═══════════════════════════════════════════════════"
        echo "按 Ctrl+C 退出监控"
        sleep 2
    done

    echo "循环已结束或文件不存在"
}

main
EOF

chmod +x monitor.sh

步骤 3:配置项目

bash
# 创建 PROMPT.md(与方案 A 相同)
cat > PROMPT.md << 'EOF'
# 自动化研究报告生成任务

[与方案 A 相同的 PROMPT.md 内容]
EOF

# 初始化状态文件
cat > .current_status.json << 'INIT'
{
  "loop_count": 0,
  "progress": 0,
  "current_task": "创建研究报告目录结构",
  "completed_tasks": [],
  "pending_tasks": [
    "创建报告目录结构",
    "撰写研究背景与意义章节",
    "撰写文献综述章节",
    "撰写技术方法论章节",
    "撰写案例分析章节",
    "撰写挑战与限制章节",
    "撰写未来发展趋势章节",
    "撰写结论与建议章节",
    "添加图表和示意图",
    "完善文献引用",
    "格式校对与排版"
  ],
  "last_update": "$(date -Iseconds)",
  "api_calls_this_hour": 0,
  "no_progress_count": 0
}
INIT

步骤 4:启动循环

bash
# 终端 1:启动主循环
./ralph-external-loop.sh

# 终端 2:启动监控
./monitor.sh

配置优化建议

GLM4.7 提示词优化

提高任务完成准确率

markdown
# 增强的 GLM4.7 提示词模板

你是一个专业的研究报告生成助手。

## 重要指令

1. **一次只做一个任务**:专注于完成一个具体的任务,不要试图一次完成所有事情
2. **明确报告进展**:完成后使用 RALPH_UPDATE 格式报告你完成了什么
3. **质量优先**:确保每个任务都高质量完成,不要匆忙推进

## 输出规范

当你完成一个任务时,必须使用以下格式:

\`\`\`
RALPH_UPDATE:
{
  "completed_task": "清晰描述你完成的任务",
  "next_task": "建议的下一个任务(基于 @fix_plan.md)",
  "progress": 新的进度百分比
}
\`\`\`

## 质量检查清单

在报告任务完成前,请自查:
- [ ] 内容是否完整
- [ ] 是否有具体的案例或数据支撑
- [ ] 格式是否正确
- [ ] 是否存在拼写或语法错误

只有通过自查后,才设置 EXIT_SIGNAL: true。

性能优化配置

bash
# 调整循环参数以优化性能

# 对于复杂任务,减少循环频率
export RALPH_LOOP_DELAY=10  # 10秒间隔

# 增加最大循环次数(如果任务复杂)
export RALPH_MAX_ITERATIONS=100

# 根据预算调整 API 限制
export RALPH_MAX_API_CALLS=50  # 每小时50次调用

# 启用详细日志以便调试
export RALPH_LOG_LEVEL=DEBUG

故障排查

常见问题 1:循环无法启动

症状:运行 ralph 后没有任何输出

排查步骤

bash
# 检查脚本权限
ls -la ralph

# 检查是否在正确的目录
pwd

# 查看错误日志
cat logs/ralph.error

# 手动测试 OpenCode
opencode -p "测试" --help

解决方案

bash
# 重新安装 Ralph
cd ~/ralph-claude-code
./install.sh

# 或添加执行权限
chmod +x ralph

常见问题 2:循环过早退出

症状:循环在 1-2 次后就停止

排查步骤

bash
# 检查输出日志
tail -n 50 logs/ralph.log

# 查看 OpenCode 错误
cat outputs/loop_0001.txt

# 检查 Stop Hook
cat hooks/stop-hook.sh

可能原因

  1. EXIT_SIGNAL 被错误地设置为 true
  2. GLM4.7 输出中包含了过多完成关键词
  3. OpenCode 调用失败

解决方案

bash
# 退出检测过于宽松,提高阈值
export MIN_COMPLETION_INDICATORS=5

# 或在 PROMPT.md 中明确指示 GLM4.7 不要设置 EXIT_SIGNAL

常见问题 3:循环陷入无限循环

症状:循环一直运行但不进展

排查步骤

bash
# 检查循环次数
cat .loop_count

# 查看最近的输出
tail outputs/loop_*.txt

# 检查断路器状态
ralph --circuit-status

可能原因

  1. GLM4.7 每次输出相同内容
  2. 任务定义不清晰
  3. 断路器未正确触发

解决方案

bash
# 手动停止循环
ralph --reset-circuit

# 重新定义更清晰的任务
vim @fix_plan.md

# 从头开始
rm .ralph_session
ralph

常见问题 4:API 速率限制

症状:显示达到速率限制,循环暂停

解决方案

bash
# 等待 60 分钟自动恢复

# 或手动重置 API 计数器
echo 0 > .api_calls
echo $(($(date +%s) + 3600)) > .hour_limit_reset

# 或者增加限制(如果预算允许)
export RALPH_MAX_API_CALLS=200

参考资料