From 0c93bb4497ae2790b32211668a902a7bef0110c3 Mon Sep 17 00:00:00 2001 From: Aska Date: Sun, 6 Sep 2026 11:39:59 +0800 Subject: [PATCH] =?UTF-8?q?docs(deploy):=20README=20=E5=85=A8=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E6=9C=AC=E5=9C=B0=E9=83=A8=E7=BD=B2=E6=96=B9=E6=A1=88?= =?UTF-8?q?=20+=20scripts/dev-up.sh=20=E4=B8=80=E9=94=AE=E5=90=AF=E5=8A=A8?= =?UTF-8?q?=EF=BC=88PG=E2=86=92llama.cpp=20embedding=E2=86=92cyrene?= =?UTF-8?q?=EF=BC=89=EF=BC=8C=E8=B7=AF=E5=BE=84=E5=9B=BA=E5=AE=9A=20~/apps?= =?UTF-8?q?=20=E4=B8=8E=20~/.models=EF=BC=8C=E5=8B=BF=E7=94=A8=20/tmp?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 60 +++++++++++++++++++++++++++++++++++++++-------- scripts/dev-up.sh | 60 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+), 10 deletions(-) create mode 100755 scripts/dev-up.sh diff --git a/README.md b/README.md index caa778f..87a8631 100644 --- a/README.md +++ b/README.md @@ -18,14 +18,22 @@ --- -## 本地部署(用户侧) +## 本地部署(用户侧 · 全流程) -### 1. 前置 -- Go 1.26、Node 22(前端构建用)、Docker(**可选**,用于 PostgreSQL + pgvector / 本地 embedding)。 +### 0. 前置 +- Go 1.26、Node 22(前端构建用)、Docker(用于 PostgreSQL + pgvector;不用 PG 可仅用 SQLite)。 + +### 1. 一键启动(最快,推荐) +```bash +bash scripts/dev-up.sh +# 依次拉起:PG+pgvector → llama.cpp embedding(Qwen3) → 前端 build → cyrene +# 访问 http://localhost:8080(按 .env 的 PORT) +``` +> `scripts/dev-up.sh` 约定:llama.cpp 放 `~/apps/llama.cpp/`、GGUF 放 `~/.models/`、cyrene 二进制 `~/apps/cyrene/cyrene`。已运行的服务会自动跳过。 ### 2. 配置 `.env`(复制 `.env.example`) ```bash -# 认证 +# 认证(JWT_SECRET 必填 ≥32) JWT_SECRET=<≥32 字符随机串> ADMIN_USERNAME=admin ADMIN_PASSWORD=<你的密码> @@ -37,24 +45,56 @@ ANTHROPIC_API_KEY= ANTHROPIC_MODEL=deepseek-chat # 或 OpenAI 兼容:LLM_PROVIDER=openai + LLM_BASE_URL/API_KEY/MODEL -# 数据库(可选增强:PG + pgvector 向量检索) +# 数据库(可选增强:PG + pgvector 向量检索;不配则用 SQLite) DB_PG_URL=postgres://cyrene:cyrene_pass@localhost:5432/cyrene_ai?sslmode=disable + +# 记忆嵌入(真语义;EMBEDDING_API_URL 必须是【完整 /v1/embeddings 端点】,不是 base) +EMBEDDING_API_URL=http://localhost:11434/v1/embeddings +EMBEDDING_MODEL=Qwen3-Embedding-0.6B ``` -### 3. 可选依赖(Docker;PG+pgvector 必需可加,embedding 可选) +### 3. 数据库(PG + pgvector,Docker) ```bash -docker compose -f docker-compose.dev.yml up -d # PG + pgvector -docker compose -f docker-compose.dev.yml --profile embedding up -d embedding # 可选:本地 embedding(Ollama) -# 若用 embedding:docker exec -it cyrene-embedding ollama pull +docker compose -f docker-compose.dev.yml up -d pg +# 首次:vector 扩展由应用自动 CREATE(本地 cyrene 用户为 superuser) ``` +> 不用 PG 可跳过;SQLite 默认即用。 -### 4. 构建并启动(单二进制,go:embed 前端) +### 4. 本地 embedding(llama.cpp + Qwen3 GGUF,走 Vulkan/GPU) +```bash +# 一次准备(llama.cpp 放 ~/apps/llama.cpp/,模型放 ~/.models/;勿用 /tmp) +mkdir -p ~/apps/llama.cpp ~/.models +# llama.cpp release(Vulkan)解压到 ~/apps/llama.cpp/ +# Qwen3-Embedding-0.6B-Q8_0.gguf(~639MB,ModelScope 下载)→ ~/.models/ +chmod 644 ~/.models/Qwen3-Embedding-0.6B-Q8_0.gguf + +# 启动 +~/apps/llama.cpp/llama-server -m ~/.models/Qwen3-Embedding-0.6B-Q8_0.gguf \ + --embedding -ngl 99 --host 127.0.0.1 --port 11434 & +``` +> **模型来源**:HuggingFace 国内不可访问,请从 **ModelScope(魔搭)** 下载 `Qwen3-Embedding-0.6B-Q8_0.gguf`。llama.cpp 只认 **GGUF**(`model.safetensors` 是 transformers/HF 用的,不能直接喂)。 + +### 5. 构建并启动(单二进制,go:embed 前端) ```bash cd frontend/web && npm ci && npm run build && cd ../.. # 产 dist(含拷到 internal/webui/dist) go build -ldflags="-s -w" -trimpath -o cyrene ./cmd/cyrene/ ./cyrene # 访问 http://localhost:8080(按 .env 的 PORT) ``` +### 6. 服务端口 / 路径速查 +| 服务 | 地址 / 路径 | 说明 | +|------|------------|------| +| Cyrene 网关 | http://localhost:8080(`.env:PORT`) | SPA + REST/WS + 面板 `/admin` | +| PG + pgvector | `localhost:5432`(docker `cyrene-pg`) | 向量索引在 `cyrene_ai` | +| llama.cpp embedding | `http://localhost:11434/v1/embeddings` | Qwen3,Vulkan | + + +### 7. 注意事项 +- **勿用 `/tmp` 放二进制/模型**(tmpfs 在内存里,堆多了会炸);一律 `~/apps/`、`~/.models/`。 +- `EMBEDDING_API_URL` **必须是完整 `/v1/embeddings`**(不是 base),否则 404。 +- **切换 embedding 模型会改维度**(Qwen3=1024,n-gram=256)→ 换模型前清一次向量表:`docker exec cyrene-pg psql -U cyrene -d cyrene_ai -c "TRUNCATE vec_items;"`(懒创建的真向量表)。 +- LLM 用 anthropic 协议时填 `ANTHROPIC_*`;用 openai 兼容时填 `LLM_*`。`LLM_PROVIDER` 二选一。 + --- ## Embedding 模型推荐 diff --git a/scripts/dev-up.sh b/scripts/dev-up.sh new file mode 100755 index 0000000..390b158 --- /dev/null +++ b/scripts/dev-up.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash +# Cyrene v2 本地一键开发启动:PG+pgvector → llama.cpp embedding → 前端 build → cyrene +# 用法:bash scripts/dev-up.sh (在仓库根目录;需 docker + go + node) +set -euo pipefail + +REPO="$(cd "$(dirname "$0")/.." && pwd)" +MODEL_DIR="$HOME/.models" +LLAMA_DIR="$HOME/apps/llama.cpp" +APP_NAME="cyrene" +APP_BIN="$HOME/apps/cyrene/$APP_NAME" +EMB_MODEL="$MODEL_DIR/Qwen3-Embedding-0.6B-Q8_0.gguf" +EMB_PORT=11434 +GW_PORT=10080 + +cd "$REPO" + +echo "==> [1/4] PostgreSQL + pgvector (docker)" +if command -v docker >/dev/null 2>&1; then + docker compose -f docker-compose.dev.yml up -d pg || echo " (docker compose up pg 失败,忽略继续——若未用 PG 可跳过)" +else + echo " (未检测到 docker;若用 SQLite 默认可不启动 PG)" +fi + +echo "==> [2/4] llama.cpp embedding (Qwen3-Embedding,Vulkan)" +if [ -x "$LLAMA_DIR/llama-server" ] && [ -f "$EMB_MODEL" ]; then + # 已在跑则跳过 + if ! curl -s --max-time 2 "http://127.0.0.1:$EMB_PORT/health" >/dev/null 2>&1; then + (cd "$LLAMA_DIR" && nohup ./llama-server -m "$EMB_MODEL" --embedding -ngl 99 --host 127.0.0.1 --port "$EMB_PORT" > "$HOME/cy-emb.log" 2>&1 &) + echo " llama-server 已启动: http://127.0.0.1:$EMB_PORT" + else + echo " llama-server 已在运行 (: $EMB_PORT),跳过" + fi +else + echo " (未找到 $LLAMA_DIR/llama-server 或模型 $EMB_MODEL;跳过。" + echo " llama.cpp 放 ~/apps/llama.cpp,GGUF 放 ~/.models/)" +fi + +echo "==> [3/4] 前端构建 (go:embed 需要 dist)" +if [ -d frontend/web ]; then + (cd frontend/web && npm ci >/dev/null 2>&1 && npm run build >/dev/null 2>&1) || echo " (前端 build 跳过/失败——若已存在 dist 可忽略)" +fi + +echo "==> [4/4] 构建并启动 cyrene" +if [ ! -f "$APP_BIN" ]; then + mkdir -p "$HOME/apps/cyrene" + echo " go build -> $APP_BIN" + go build -ldflags="-s -w" -trimpath -o "$APP_BIN" ./cmd/cyrene +fi +if ! curl -s --max-time 2 "http://127.0.0.1:$GW_PORT/api/v1/health" >/dev/null 2>&1; then + (cd "$REPO" && nohup "$APP_BIN" > "$HOME/cy.log" 2>&1 &) + echo " cyrene 已启动: http://localhost:$GW_PORT (日志 $HOME/cy.log)" +else + echo " cyrene 已在运行 (: $GW_PORT),跳过" +fi + +echo +echo "完成。访问 http://localhost:$GW_PORT (.env 的 PORT 覆盖此值)" +echo " · LLM: .env 的 LLM_PROVIDER / ANTHROPIC_* 或 LLM_*" +echo " · 向量: EMBEDDING_API_URL=http://127.0.0.1:$EMB_PORT/v1/embeddings EMBEDDING_MODEL=Qwen3-Embedding-0.6B" +echo " · 停止: pkill -f llama-server ; pkill -f $APP_NAME"