From 4ff6afe9427293e92aa9ae2fac421af3562c79e6 Mon Sep 17 00:00:00 2001 From: limingjing6666 Date: Sat, 9 May 2026 23:50:58 +0800 Subject: [PATCH 1/3] @ fix: add missing Guava version and jspecify dependency - Guava dependency lacked tag, causing Maven compilation failure - jspecify is an optional transitive dependency of Guava not resolved automatically - ApplicationContextHolder uses @NonNull from jspecify, causing "symbol not found" Both issues block compilation with "mvn clean install" on any machine. Co-Authored-By: Claude Opus 4.7 @ --- framework/pom.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/framework/pom.xml b/framework/pom.xml index d47e4477..1d2ce18f 100644 --- a/framework/pom.xml +++ b/framework/pom.xml @@ -34,6 +34,13 @@ com.google.guava guava + 33.4.0-jre + + + + org.jspecify + jspecify + 1.0.0 From 3a16a247e9cafe07d4a27ff8325f32f1750de05f Mon Sep 17 00:00:00 2001 From: limingjing6666 Date: Sat, 9 May 2026 23:58:18 +0800 Subject: [PATCH 2/3] @ feat: add local dev quickstart with unified compose and startup scripts - docker-compose.local.yml: one-command start for all infrastructure (PostgreSQL, Redis, RustFS, Milvus, RocketMQ) - scripts/start-local.sh: macOS/Linux one-click startup script - scripts/start-local.ps1: Windows PowerShell startup script - docs/LOCAL_DEV.md: detailed local development guide covering prerequisites, build fixes, service startup, and troubleshooting Co-Authored-By: Claude Opus 4.7 @ --- docker-compose.local.yml | 204 +++++++++++++++++++++++ docs/LOCAL_DEV.md | 339 +++++++++++++++++++++++++++++++++++++++ scripts/start-local.ps1 | 92 +++++++++++ scripts/start-local.sh | 87 ++++++++++ 4 files changed, 722 insertions(+) create mode 100644 docker-compose.local.yml create mode 100644 docs/LOCAL_DEV.md create mode 100644 scripts/start-local.ps1 create mode 100644 scripts/start-local.sh diff --git a/docker-compose.local.yml b/docker-compose.local.yml new file mode 100644 index 00000000..28552943 --- /dev/null +++ b/docker-compose.local.yml @@ -0,0 +1,204 @@ +name: ragent-local + +services: + # ============================================= + # PostgreSQL with pgvector extension + # ============================================= + postgres: + container_name: ragent-postgres + image: pgvector/pgvector:pg17 + environment: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: ragent + ports: + - "5432:5432" + volumes: + - pgdata:/var/lib/postgresql/data + - ../resources/database/schema_pg.sql:/docker-entrypoint-initdb.d/01_schema.sql + - ../resources/database/init_data_pg.sql:/docker-entrypoint-initdb.d/02_init_data.sql + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres -d ragent"] + interval: 10s + timeout: 5s + retries: 5 + + # ============================================= + # Redis + # ============================================= + redis: + container_name: ragent-redis + image: redis:7-alpine + ports: + - "6379:6379" + command: redis-server --requirepass 123456 + healthcheck: + test: ["CMD", "redis-cli", "-a", "123456", "ping"] + interval: 10s + timeout: 5s + retries: 5 + + # ============================================= + # RustFS - S3 compatible object storage + # ============================================= + rustfs: + container_name: ragent-rustfs + image: rustfs/rustfs:1.0.0-alpha.72 + command: + - "--address" + - ":9000" + - "--console-enable" + - "--access-key" + - "rustfsadmin" + - "--secret-key" + - "rustfsadmin" + - "/data" + environment: + - RUSTFS_ACCESS_KEY=rustfsadmin + - RUSTFS_SECRET_KEY=rustfsadmin + - RUSTFS_CONSOLE_ENABLE=true + ports: + - "9000:9000" + - "9001:9001" + volumes: + - rustfs-data:/data + healthcheck: + test: ["CMD", "sh", "-c", "wget -qO- http://localhost:9000/ || exit 1"] + interval: 30s + timeout: 10s + retries: 5 + + # ============================================= + # etcd - required by Milvus + # ============================================= + etcd: + container_name: ragent-etcd + image: quay.io/coreos/etcd:v3.5.18 + environment: + - ETCD_AUTO_COMPACTION_MODE=revision + - ETCD_AUTO_COMPACTION_RETENTION=1000 + - ETCD_QUOTA_BACKEND_BYTES=4294967296 + - ETCD_SNAPSHOT_COUNT=50000 + command: > + etcd + -advertise-client-urls=http://etcd:2379 + -listen-client-urls http://0.0.0.0:2379 + --data-dir /etcd + volumes: + - etcd-data:/etcd + healthcheck: + test: ["CMD", "etcdctl", "endpoint", "health"] + interval: 30s + timeout: 20s + retries: 3 + + # ============================================= + # Milvus - vector database (optional with pgvector) + # ============================================= + milvus: + container_name: ragent-milvus + image: milvusdb/milvus:v2.6.6 + command: ["milvus", "run", "standalone"] + security_opt: + - seccomp:unconfined + environment: + ETCD_ENDPOINTS: etcd:2379 + MINIO_ADDRESS: rustfs:9000 + MINIO_ACCESS_KEY_ID: rustfsadmin + MINIO_SECRET_ACCESS_KEY: rustfsadmin + volumes: + - milvus-data:/var/lib/milvus + ports: + - "19530:19530" + - "9091:9091" + depends_on: + etcd: + condition: service_healthy + rustfs: + condition: service_healthy + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:9091/healthz"] + interval: 30s + start_period: 90s + timeout: 20s + retries: 3 + + # ============================================= + # RocketMQ Name Server + # ============================================= + rmqnamesrv: + container_name: ragent-rmqnamesrv + image: apache/rocketmq:5.2.0 + ports: + - "9876:9876" + environment: + JAVA_OPT_EXT: "-Xms256m -Xmx400m" + command: sh mqnamesrv + healthcheck: + test: ["CMD-SHELL", "grep -q 'The Name Server boot success' /home/rocketmq/logs/rocketmqlogs/namesrv.log || exit 1"] + interval: 10s + timeout: 5s + retries: 10 + restart: unless-stopped + + # ============================================= + # RocketMQ Broker + # ============================================= + rmqbroker: + container_name: ragent-rmqbroker + image: apache/rocketmq:5.2.0 + ports: + - "10912:10912" + - "10911:10911" + - "10909:10909" + - "8080:8080" + - "8081:8081" + environment: + NAMESRV_ADDR: "rmqnamesrv:9876" + JAVA_OPT_EXT: "-Xms512m -Xmx512m" + depends_on: + rmqnamesrv: + condition: service_healthy + command: + - sh + - -c + - | + cat > /home/rocketmq/rocketmq-5.2.0/conf/broker.conf << EOF + brokerClusterName = DefaultCluster + brokerName = broker-a + brokerId = 0 + deleteWhen = 04 + fileReservedTime = 48 + brokerRole = ASYNC_MASTER + flushDiskType = ASYNC_FLUSH + brokerIP1 = 127.0.0.1 + timerMaxDelaySec = 31622400 + EOF + sh mqbroker --enable-proxy \ + -c /home/rocketmq/rocketmq-5.2.0/conf/broker.conf + restart: unless-stopped + + # ============================================= + # RocketMQ Dashboard (optional) + # ============================================= + rmqdashboard: + container_name: ragent-rmqdashboard + image: apacherocketmq/rocketmq-dashboard:2.1.0 + network_mode: "service:rmqbroker" + environment: + JAVA_OPTS: >- + -Xms256m -Xmx512m + -XX:MaxMetaspaceSize=256m + -Drocketmq.config.enableDashBoardCollect=false + -Drocketmq.namesrv.addr=rmqnamesrv:9876 + -Dserver.port=8082 + depends_on: + rmqbroker: + condition: service_started + restart: unless-stopped + +volumes: + pgdata: + rustfs-data: + etcd-data: + milvus-data: diff --git a/docs/LOCAL_DEV.md b/docs/LOCAL_DEV.md new file mode 100644 index 00000000..3233175e --- /dev/null +++ b/docs/LOCAL_DEV.md @@ -0,0 +1,339 @@ +# Ragent AI 本地启动教程 + +> 适用环境:Windows / macOS / Linux,需 Docker、JDK 17+、Node.js 18+。 + +--- + +## 第一步:环境准备 + +确保已安装以下工具: + +| 工具 | 验证命令 | 要求版本 | +|:---|:---|:---| +| Docker | `docker --version` | 20.x+ | +| JDK | `java -version` | 17+ | +| Maven | `mvn --version` | 不用装,项目自带 mvnw | +| Node.js | `node --version` | 18+ | +| npm | `npm --version` | 9+ | + +--- + +## 第二步:克隆项目 + +```bash +git clone https://github.com/nageoffer/ragent.git +cd ragent +``` + +--- + +## 第三步:修复 Maven 编译错误(必做) + +项目有一个致命 Bug —— `framework/pom.xml` 中 Guava 依赖缺少版本号,Maven 会直接编译失败。 + +打开 `framework/pom.xml`,找到第 34-37 行: + +```xml + + com.google.guava + guava + +``` + +改为: + +```xml + + com.google.guava + guava + 33.4.0-jre + +``` + +> 这是阻止编译的**第一道坎**,不改后面全是白费。 + +--- + +还需要修复一个隐藏依赖 —— Guava 的传递依赖 `org.jspecify:jspecify` 标记为 optional,不会自动传递。`ApplicationContextHolder.java` 引用了 `@NonNull` 注解,缺少这个依赖同样编译失败。 + +在 `framework/pom.xml` 的 Guava 依赖后面加上: + +```xml + + org.jspecify + jspecify + 1.0.0 + +``` + +> 以上两个 POM 修改经真实环境踩坑验证,缺一不可。 + +--- + +## 第四步:启动基础设施(Docker) + +项目依赖 5 个外部服务:PostgreSQL、Redis、RocketMQ、Milvus(含 RustFS S3)。 + +### 4.1 启动 Milvus + RustFS(S3) + +RustFS 提供 S3 兼容的对象存储,Milvus 依赖它,所以先起这个堆栈: + +```bash +docker compose -f resources/docker/milvus-stack-2.6.6.compose.yaml up -d +``` + +等待健康检查通过(约 1-2 分钟): +```bash +docker ps +``` + +确认这四个容器都是 `healthy` 状态:`rustfs`、`etcd`、`milvus-standalone`、`milvus-attu`。 + +### 4.2 启动 RocketMQ + +```bash +docker compose -f resources/docker/rocketmq-stack-5.2.0.compose.yaml up -d +``` + +确认 `rmqnamesrv`、`rmqbroker`、`rocketmq-dashboard` 都在运行。 + +### 4.3 启动 PostgreSQL 和 Redis + +这两个项目 docker-compose 里没带,需要自己起。最快的方式: + +```bash +# PostgreSQL(必须安装 pgvector 扩展) +docker run -d --name postgres-ragent \ + -e POSTGRES_USER=postgres \ + -e POSTGRES_PASSWORD=postgres \ + -e POSTGRES_DB=ragent \ + -p 5432:5432 \ + pgvector/pgvector:pg17 + +# Redis +docker run -d --name redis-ragent \ + -p 6379:6379 \ + redis:7-alpine \ + redis-server --requirepass 123456 +``` + +> 注意:必须用 `pgvector/pgvector` 镜像,普通 PostgreSQL 没有向量扩展。 + +--- + +## 第五步:初始化数据库 + +```bash +# 建表 +docker exec -i postgres-ragent psql -U postgres -d ragent < resources/database/schema_pg.sql + +# 导入初始数据(admin/admin 用户) +docker exec -i postgres-ragent psql -U postgres -d ragent < resources/database/init_data_pg.sql +``` + +验证一下: +```bash +docker exec -i postgres-ragent psql -U postgres -d ragent -c "SELECT username, role FROM t_user;" +``` + +应该看到一行 `admin | admin`。 + +--- + +## 第六步:配置 API Key(运行 AI 能力必做) + +`bootstrap/src/main/resources/application.yaml` 中的默认聊天模型 `qwen3-max` 和嵌入模型都走远程 API,需要设置环境变量: + +**Windows (PowerShell):** +```powershell +$env:BAILIAN_API_KEY = "你的阿里云百炼APIKey" +$env:SILICONFLOW_API_KEY = "你的SiliconFlow APIKey" +``` + +**macOS / Linux:** +```bash +export BAILIAN_API_KEY="你的阿里云百炼APIKey" +export SILICONFLOW_API_KEY="你的SiliconFlow APIKey" +``` + +> 如果没有 API Key 又不想花钱,可以改用本地 Ollama。参考文末的「可选:纯本地模式」。 + +申请地址: +- 百炼:https://bailian.console.aliyun.com +- SiliconFlow:https://siliconflow.cn + +--- + +## 第七步:编译项目 + +```bash +./mvnw clean install -DskipTests +``` + +Windows 用 `mvnw.cmd`: +```cmd +mvnw.cmd clean install -DskipTests +``` + +看到 `BUILD SUCCESS` 继续下一步。 + +--- + +## 第八步:启动 MCP 服务端 + +开第一个终端: + +```bash +cd mcp-server +../mvnw spring-boot:run +``` + +默认端口 `9099`,看到 `Started McpServerApplication` 即成功。 + +--- + +## 第九步:启动主应用 + +开第二个终端,回到项目根目录: + +```bash +cd bootstrap +../mvnw spring-boot:run +``` + +默认端口 `9090`,上下文路径 `/api/ragent`。 + +看到 `Started RagentApplication` 且没有异常日志,后端启动成功。 + +--- + +## 第十步:启动前端 + +开第三个终端: + +```bash +cd frontend +npm install +npm run dev +``` + +默认端口 `5173`,浏览器访问 http://localhost:5173 + +登录账号:`admin` / `admin` + +--- + +## 第十一步:验证 + +1. 浏览器打开 http://localhost:5173,用 `admin/admin` 登录 +2. 新建一个知识库,上传一份文档 +3. 在对话框里提问,看是否能正常检索和生成回答 + +--- + +## 常见问题 + +### Q1: 编译报 `找不到org.jspecify.annotations包` 或 `找不到符号: 类 NonNull` + +第三步 jspecify 依赖没加,回到第三步加上 `org.jspecify:jspecify:1.0.0`。 + +### Q2: 编译报 `dependencies.dependency.version' for guava is missing` + +第三步没做,回到第三步修复 Guava 版本号。 + +### Q2: 启动报 `SnowflakeIdInitializer` 相关错误 + +Redis 没启动或密码不对。检查: +```bash +docker ps | grep redis-ragent +``` +确认 Redis 密码是 `123456`(和 `application.yaml` 中一致)。 + +### Q3: 启动报 `Connection to 127.0.0.1:5432 refused` + +PostgreSQL 没启动。检查: +```bash +docker ps | grep postgres-ragent +``` + +### Q4: 启动报 `relation "t_user" does not exist` + +数据库表没建。回到第五步执行 SQL。 + +### Q5: 调用 AI 时报 401 或认证错误 + +API Key 没设或过期。检查环境变量: +```bash +echo $BAILIAN_API_KEY +echo $SILICONFLOW_API_KEY +``` + +### Q6: 知识库上传文档失败 + +RustFS (S3) 没启动。检查: +```bash +docker ps | grep rustfs +``` + +### Q7: RocketMQ 连接报错 + +```bash +docker ps | grep rmq +``` +确认 `rmqnamesrv` 和 `rmqbroker` 都在运行。 + +--- + +## 可选:纯本地模式(不需要任何 API Key) + +如果不想申请远程 API Key,可以用 Ollama 跑本地模型。 + +### 1. 安装 Ollama + +```bash +# macOS / Linux +curl -fsSL https://ollama.com/install.sh | sh + +# Windows: 从 ollama.com 下载安装包 +``` + +### 2. 拉取模型 + +```bash +ollama pull qwen3:8b-fp16 +ollama pull qwen3-embedding:8b-fp16 +``` + +### 3. 修改配置 + +编辑 `bootstrap/src/main/resources/application.yaml`: + +```yaml +# 将默认模型从远程切到本地 +ai: + chat: + default-model: qwen3-local # 原来是 qwen3-max + deep-thinking-model: qwen3-local # 原来是 qwen3-max + embedding: + default-model: qwen-emb-local # 原来是 qwen-emb-8b +``` + +这样就不需要设 `BAILIAN_API_KEY` 和 `SILICONFLOW_API_KEY` 了。 + +> 注意:本地 8B 模型效果不如云端大模型,仅适合开发调试。 + +--- + +## 服务端口一览 + +| 服务 | 端口 | 用途 | +|:---|:---|:---| +| 主应用 | 9090 | 后端 API + SSE | +| MCP Server | 9099 | MCP 工具调用 | +| 前端 | 5173 | React 前端页面 | +| PostgreSQL | 5432 | 业务数据库 + pgvector | +| Redis | 6379 | 缓存 / 分布式 ID | +| RocketMQ | 9876 / 10909-10912 | 消息队列 | +| Milvus | 19530 | 向量数据库(pgvector 模式下不实际使用) | +| RustFS | 9000 / 9001 | S3 对象存储 | +| Ollama | 11434 | 本地模型推理 | diff --git a/scripts/start-local.ps1 b/scripts/start-local.ps1 new file mode 100644 index 00000000..3337283e --- /dev/null +++ b/scripts/start-local.ps1 @@ -0,0 +1,92 @@ +# ============================================= +# Ragent AI - 本地一键启动脚本 +# Windows PowerShell +# ============================================= + +$ErrorActionPreference = "Stop" +$ProjectRoot = (Get-Item $PSScriptRoot).Parent.FullName +Set-Location $ProjectRoot + +function Info { Write-Host "[INFO] $args" -ForegroundColor Green } +function Warn { Write-Host "[WARN] $args" -ForegroundColor Yellow } +function Error { Write-Host "[ERROR] $args" -ForegroundColor Red; exit 1 } + +# ---- Step 1: Check prerequisites ---- +Info "检查运行环境..." + +if (-not (Get-Command docker -ErrorAction SilentlyContinue)) { + Error "请先安装 Docker: https://docs.docker.com/get-docker/" +} +if (-not (Get-Command java -ErrorAction SilentlyContinue)) { + Error "请先安装 JDK 17+: https://adoptium.net" +} +if (-not (Get-Command node -ErrorAction SilentlyContinue)) { + Error "请先安装 Node.js 18+: https://nodejs.org" +} + +Info "环境检查通过" + +# ---- Step 2: Start Docker services ---- +Info "启动基础设施..." +docker compose -f docker-compose.local.yml up -d + +Info "等待 PostgreSQL 就绪..." +do { + Start-Sleep 2 + $ready = docker exec ragent-postgres pg_isready -U postgres -d ragent 2>$null +} until ($LASTEXITCODE -eq 0) +Info "PostgreSQL 已就绪" + +Info "等待 Milvus 就绪..." +Start-Sleep 30 + +# ---- Step 3: Build backend ---- +Info "编译后端..." +./mvnw.cmd clean install -DskipTests + +# ---- Step 4: Start MCP Server ---- +Info "启动 MCP Server (端口 9099)..." +$MCPJob = Start-Job -ScriptBlock { + Set-Location "$using:ProjectRoot/mcp-server" + & "$using:ProjectRoot/mvnw.cmd" spring-boot:run 2>&1 +} + +Start-Sleep 8 + +# ---- Step 5: Start main backend ---- +Info "启动主应用 (端口 9090)..." +$BootstrapJob = Start-Job -ScriptBlock { + Set-Location "$using:ProjectRoot/bootstrap" + & "$using:ProjectRoot/mvnw.cmd" spring-boot:run 2>&1 +} + +Start-Sleep 25 + +# ---- Step 6: Start frontend ---- +Info "安装前端依赖..." +Set-Location "$ProjectRoot/frontend" +npm install --silent + +Info "启动前端 (端口 5173)..." +$FrontendJob = Start-Job -ScriptBlock { + Set-Location "$using:ProjectRoot/frontend" + npm run dev 2>&1 +} + +Start-Sleep 6 + +# ---- Done ---- +Set-Location $ProjectRoot +Write-Host "" +Write-Host "========================================" +Write-Host " Ragent AI 已启动" +Write-Host "========================================" +Write-Host " 前端: http://localhost:5173" +Write-Host " 后端 API: http://localhost:9090/api/ragent" +Write-Host " MCP: http://localhost:9099" +Write-Host " 登录账号: admin / admin" +Write-Host "========================================" +Write-Host "" +Info "停止服务: Stop-Job -Id $($MCPJob.Id), $($BootstrapJob.Id), $($FrontendJob.Id)" + +Wait-Job diff --git a/scripts/start-local.sh b/scripts/start-local.sh new file mode 100644 index 00000000..19834a6b --- /dev/null +++ b/scripts/start-local.sh @@ -0,0 +1,87 @@ +#!/usr/bin/env bash +set -euo pipefail + +# ============================================= +# Ragent AI - 本地一键启动脚本 +# macOS / Linux +# ============================================= + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +info() { echo -e "${GREEN}[INFO]${NC} $*"; } +warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } +error() { echo -e "${RED}[ERROR]${NC} $*"; exit 1; } + +PROJECT_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +cd "$PROJECT_ROOT" + +# ---- Step 1: Check prerequisites ---- +info "检查运行环境..." + +command -v docker >/dev/null 2>&1 || error "请先安装 Docker: https://docs.docker.com/get-docker/" +command -v java >/dev/null 2>&1 || error "请先安装 JDK 17+: https://adoptium.net" +command -v node >/dev/null 2>&1 || error "请先安装 Node.js 18+: https://nodejs.org" + +info "环境检查通过" + +# ---- Step 2: Start Docker services ---- +info "启动基础设施..." +docker compose -f docker-compose.local.yml up -d + +info "等待 PostgreSQL 就绪..." +until docker exec ragent-postgres pg_isready -U postgres -d ragent 2>/dev/null; do + sleep 2 +done +info "PostgreSQL 已就绪" + +# ---- Step 3: Build backend ---- +info "编译后端..." +./mvnw clean install -DskipTests + +# ---- Step 4: Start MCP Server ---- +info "启动 MCP Server (端口 9099)..." +cd "$PROJECT_ROOT/mcp-server" +../mvnw spring-boot:run & +MCP_PID=$! +cd "$PROJECT_ROOT" + +sleep 5 + +# ---- Step 5: Start main backend ---- +info "启动主应用 (端口 9090)..." +cd "$PROJECT_ROOT/bootstrap" +../mvnw spring-boot:run & +BOOTSTRAP_PID=$! +cd "$PROJECT_ROOT" + +sleep 20 + +# ---- Step 6: Start frontend ---- +info "安装前端依赖..." +cd "$PROJECT_ROOT/frontend" +npm install --silent + +info "启动前端 (端口 5173)..." +npm run dev & +FRONTEND_PID=$! +cd "$PROJECT_ROOT" + +sleep 5 + +# ---- Done ---- +echo "" +echo "========================================" +echo " Ragent AI 已启动" +echo "========================================" +echo " 前端: http://localhost:5173" +echo " 后端 API: http://localhost:9090/api/ragent" +echo " MCP: http://localhost:9099" +echo " 登录账号: admin / admin" +echo "========================================" +echo "" +info "如需停止所有服务,运行: kill $MCP_PID $BOOTSTRAP_PID $FRONTEND_PID" + +wait From b52f6d650e74ff75889426851f3b94f0f4ea2998 Mon Sep 17 00:00:00 2001 From: limingjing6666 Date: Sun, 10 May 2026 00:07:48 +0800 Subject: [PATCH 3/3] Revert "@" This reverts commit 4ff6afe9427293e92aa9ae2fac421af3562c79e6. --- framework/pom.xml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/framework/pom.xml b/framework/pom.xml index 1d2ce18f..d47e4477 100644 --- a/framework/pom.xml +++ b/framework/pom.xml @@ -34,13 +34,6 @@ com.google.guava guava - 33.4.0-jre - - - - org.jspecify - jspecify - 1.0.0