From 0539bac20160fceff718d91beb9d0ba30aa42a3e Mon Sep 17 00:00:00 2001 From: Feizhi Cai Date: Thu, 12 Feb 2026 21:20:46 +0800 Subject: [PATCH] docs: add developer setup guides and improve deployment scripts - Add developer setup guides (English and Chinese) - Update README to link to developer guides - Fix launch_backend_service.sh to start sync_data_source service - Add Tailwind CSS plugin auto-fix script - Update service_conf.yaml for SeekDB deployment - Update pyproject.toml dependencies --- README.md | 5 +- README_zh.md | 5 +- conf/service_conf.yaml | 24 ++- docker/launch_backend_service.sh | 57 +++++- docs/developer-setup-guide-zh.md | 257 ++++++++++++++++++++++++++ docs/developer-setup-guide.md | 255 +++++++++++++++++++++++++ pyproject.toml | 3 +- uv.lock | 15 +- uv.toml | 3 + web/package.json | 2 +- web/scripts/fix-tailwindcss-plugin.js | 78 ++++++++ 11 files changed, 682 insertions(+), 22 deletions(-) create mode 100644 docs/developer-setup-guide-zh.md create mode 100644 docs/developer-setup-guide.md create mode 100644 uv.toml create mode 100755 web/scripts/fix-tailwindcss-plugin.js diff --git a/README.md b/README.md index 42893f683..59afcffd5 100644 --- a/README.md +++ b/README.md @@ -154,7 +154,10 @@ This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENS ## Development Guide -> **TODO**: Development guide content to be added +For developers who want to build and run PowerRAG from source code: + +- **[Developer Setup Guide](docs/developer-setup-guide.md)**: Complete guide for deploying PowerRAG from source code + --- diff --git a/README_zh.md b/README_zh.md index db673ab3c..4d32f228f 100644 --- a/README_zh.md +++ b/README_zh.md @@ -153,7 +153,10 @@ PowerRAG 作为独立的后端服务运行: ## 开发手册 -> **TODO**: 开发手册内容待补充 +对于想要从源码构建和运行 PowerRAG 的开发者: + +- **[开发者部署手册](docs/developer-setup-guide-zh.md)**: 从源码部署 PowerRAG 的完整指南 + --- diff --git a/conf/service_conf.yaml b/conf/service_conf.yaml index 68f2c7854..e2f3a93bb 100644 --- a/conf/service_conf.yaml +++ b/conf/service_conf.yaml @@ -5,11 +5,11 @@ admin: host: 0.0.0.0 http_port: 9381 mysql: - name: 'rag_flow' + name: 'powerrag' user: 'root' - password: 'infini_rag_flow' - host: 'localhost' - port: 5455 + password: 'powerrag' + host: '127.0.0.1' + port: 2881 max_connections: 900 stale_timeout: 300 max_allowed_packet: 1073741824 @@ -31,12 +31,12 @@ infinity: uri: 'localhost:23817' db_name: 'default_db' oceanbase: - scheme: 'oceanbase' # set 'mysql' to create connection using mysql config + scheme: 'mysql' config: - db_name: 'test' - user: 'root@ragflow' - password: 'infini_rag_flow' - host: 'localhost' + db_name: 'powerrag_doc' + user: 'root' + password: 'powerrag' + host: '127.0.0.1' port: 2881 redis: db: 1 @@ -53,8 +53,12 @@ redis: # # 如果不配置此项,将自动降级到本地 mineru CLI(需要通过 pip install -U 'mineru[core]' 安装) # dots_ocr: # vllm_url: 'http://localhost:8020' +opendal: + scheme: 'mysql' + config: + oss_table: 'opendal_storage' task_executor: - message_queue_type: 'redis' + message_queue_type: 'oceanbase' user_default_llm: default_models: embedding_model: diff --git a/docker/launch_backend_service.sh b/docker/launch_backend_service.sh index c76381fa8..a3427ec05 100755 --- a/docker/launch_backend_service.sh +++ b/docker/launch_backend_service.sh @@ -24,12 +24,25 @@ load_env_file() { # Load environment variables load_env_file +# Get the project root directory (parent of docker directory) +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +cd "$PROJECT_ROOT" + # Unset HTTP proxies that might be set by Docker daemon export http_proxy=""; export https_proxy=""; export no_proxy=""; export HTTP_PROXY=""; export HTTPS_PROXY=""; export NO_PROXY="" -export PYTHONPATH=$(pwd) +export PYTHONPATH="$PROJECT_ROOT" export LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/ -JEMALLOC_PATH=$(pkg-config --variable=libdir jemalloc)/libjemalloc.so + +# Try to find jemalloc, but don't fail if not found +JEMALLOC_PATH="" +if command -v pkg-config >/dev/null 2>&1; then + JEMALLOC_LIBDIR=$(pkg-config --variable=libdir jemalloc 2>/dev/null || echo "") + if [ -n "$JEMALLOC_LIBDIR" ] && [ -f "$JEMALLOC_LIBDIR/libjemalloc.so" ]; then + JEMALLOC_PATH="$JEMALLOC_LIBDIR/libjemalloc.so" + fi +fi PY=python3 @@ -48,7 +61,12 @@ STOP=false PIDS=() # Set the path to the NLTK data directory -export NLTK_DATA="./nltk_data" +export NLTK_DATA="$PROJECT_ROOT/nltk_data" + +# Set additional environment variables for OceanBase +export DOC_ENGINE=${DOC_ENGINE:-oceanbase} +export STORAGE_IMPL=${STORAGE_IMPL:-OPENDAL} +export CACHE_TYPE=${CACHE_TYPE:-oceanbase} # Function to handle termination signals cleanup() { @@ -73,7 +91,11 @@ task_exe(){ local retry_count=0 while ! $STOP && [ $retry_count -lt $MAX_RETRIES ]; do echo "Starting task_executor.py for task $task_id (Attempt $((retry_count+1)))" - LD_PRELOAD=$JEMALLOC_PATH $PY rag/svr/task_executor.py "$task_id" + if [ -n "$JEMALLOC_PATH" ]; then + LD_PRELOAD=$JEMALLOC_PATH $PY rag/svr/task_executor.py "$task_id" + else + $PY rag/svr/task_executor.py "$task_id" + fi EXIT_CODE=$? if [ $EXIT_CODE -eq 0 ]; then echo "task_executor.py for task $task_id exited successfully." @@ -114,6 +136,29 @@ run_server(){ fi } +# Function to execute sync_data_source with retry logic +run_sync_data_source(){ + local retry_count=0 + while ! $STOP && [ $retry_count -lt $MAX_RETRIES ]; do + echo "Starting sync_data_source.py (Attempt $((retry_count+1)))" + $PY rag/svr/sync_data_source.py + EXIT_CODE=$? + if [ $EXIT_CODE -eq 0 ]; then + echo "sync_data_source.py exited successfully." + break + else + echo "sync_data_source.py failed with exit code $EXIT_CODE. Retrying..." >&2 + retry_count=$((retry_count + 1)) + sleep 2 + fi + done + + if [ $retry_count -ge $MAX_RETRIES ]; then + echo "sync_data_source.py failed after $MAX_RETRIES attempts. Exiting..." >&2 + cleanup + fi +} + # Start task executors for ((i=0;i 本手册记录了基于源码从零部署 PowerRAG 的完整流程,数据库使用 SeekDB (OceanBase) Docker 容器,适用于本地开发环境。 + +--- + +## 目录 + +- [快速启动](#快速启动) +- [1. 环境要求](#1-环境要求) +- [2. 数据库部署(SeekDB)](#2-数据库部署seekdb) +- [3. 后端部署](#3-后端部署) +- [4. 前端部署](#4-前端部署) +- [5. 常见问题与解决方案](#5-常见问题与解决方案) + +--- + +## 快速启动 + +以下是完整部署的快速参考命令: + +```bash +# 1. 启动 SeekDB 数据库 +docker run -d --name powerrag-seekdb \ + -p 2881:2881 \ + -e ROOT_PASSWORD=powerrag \ + -e INIT_SCRIPTS_PATH=/root/boot/init.d \ + -v $(pwd)/docker/oceanbase/init.d:/root/boot/init.d \ + oceanbase/seekdb:1.0.0.0-100000262025111218 + +# 2. 等待数据库就绪 & 创建数据库 +sleep 60 +mysql -h127.0.0.1 -P2881 -uroot -ppowerrag -e \ + "CREATE DATABASE IF NOT EXISTS powerrag; CREATE DATABASE IF NOT EXISTS powerrag_doc;" + +# 3. 安装 Python 依赖 +uv sync --python 3.12 --all-extras + +# 4. 下载模型与 NLP 资源 +docker pull infiniflow/ragflow_deps:latest +bash set_backend_deps.sh + +# 5. 启动后端 +source .venv/bin/activate +export PYTHONPATH=$(pwd) +bash docker/launch_backend_service.sh & + +# 6. 安装前端依赖 +cd web +npm install + +# 7. 启动前端 +npm run dev & + +# 8. 访问 +# 前端:http://localhost:9222 +# API:http://localhost:9380 +``` + +--- + +## 1. 环境要求 + +| 组件 | 版本要求 | 说明 | +|------|---------|------| +| **操作系统** | Linux (x86_64) | 已在 AlmaLinux 8 (kernel 5.10) 上验证 | +| **Python** | ≥ 3.12, < 3.15 | 推荐 3.12.x | +| **uv** | ≥ 0.9.x | Python 包管理器 | +| **Node.js** | ≥ 22.x | 前端构建 | +| **npm** | ≥ 10.x | 前端包管理 | +| **Docker** | ≥ 20.x | 运行 SeekDB 数据库 | +| **磁盘空间** | ≥ 50GB | 数据库 + 模型文件 + 依赖 | +| **内存** | ≥ 16GB | SeekDB 推荐 10GB+,应用服务 4GB+ | + +--- + +## 2. 数据库部署(SeekDB) + +### 2.1 启动 SeekDB 容器 + +```bash +docker run -d \ + --name powerrag-seekdb \ + -p 2881:2881 \ + -e ROOT_PASSWORD=powerrag \ + -e INIT_SCRIPTS_PATH=/root/boot/init.d \ + -v $(pwd)/docker/oceanbase/init.d:/root/boot/init.d \ + oceanbase/seekdb:1.0.0.0-100000262025111218 +``` + +> **说明**: +> - `ROOT_PASSWORD=powerrag`:设置数据库 root 密码,需与 `conf/service_conf.yaml` 中的配置保持一致 +> - 初始化脚本 `docker/oceanbase/init.d/vec_memory.sql` 会执行 `ALTER SYSTEM SET ob_vector_memory_limit_percentage = 30;`,为向量搜索分配内存 +> - 端口 `2881` 是 OceanBase 的 MySQL 协议端口 + +### 2.2 等待数据库就绪 + +SeekDB 启动需要约 30-60 秒。验证方法: + +```bash +# 检查容器健康状态 +docker ps --filter name=powerrag-seekdb --format 'table {{.Names}}\t{{.Status}}' + +# 测试连接 +mysql -h127.0.0.1 -P2881 -uroot -ppowerrag -e "SELECT 1;" +``` + +### 2.3 创建数据库 + +```bash +mysql -h127.0.0.1 -P2881 -uroot -ppowerrag -e " + CREATE DATABASE IF NOT EXISTS powerrag; + CREATE DATABASE IF NOT EXISTS powerrag_doc; +" +``` + +--- + +## 3. 后端部署 + +### 3.1 Python 依赖安装 + +```bash +cd /path/to/powerrag +uv sync --python 3.12 --all-extras +``` + +> **预计耗时**:首次安装约 10-20 分钟(取决于网络速度)。 +> +> 项目已在 `pyproject.toml` 中配置了清华 PyPI 镜像源,国内网络可直接使用。 + +### 3.2 模型与 NLP 资源下载 + +PowerRAG 依赖多个预训练模型和 NLP 数据集。推荐使用预构建的 Docker 镜像快速获取: + +```bash +# 先拉取依赖镜像 +docker pull infiniflow/ragflow_deps:latest + +# 执行依赖复制脚本 +bash set_backend_deps.sh +``` + +该脚本会从 `infiniflow/ragflow_deps:latest` 镜像中复制以下资源: + +| 资源 | 目标路径 | 用途 | +|------|---------|------| +| HuggingFace 深度文档模型 | `rag/res/deepdoc/` | 文档布局分析 | +| XGBoost 文本拼接模型 | `rag/res/deepdoc/` | 文本段落合并 | +| BAAI/bge-large-zh-v1.5 | `~/.ragflow/` | 中文向量嵌入 | +| BCE Embedding | `~/.ragflow/` | 向量嵌入 | +| NLTK 数据 | `nltk_data/` | 自然语言处理 | +| Tika Server | `tika-server-standard-3.0.0.jar` | 文档解析 | +| tiktoken 编码 | `9b5ad71b2ce5302211f9c61530b329a4922fc6a4` | Token 计算 | + +### 3.3 启动后端服务 + +```bash +source .venv/bin/activate +export PYTHONPATH=$(pwd) + +# 使用启动脚本(同时启动 API Server、Task Executor 和 Data Sync 服务) +bash docker/launch_backend_service.sh +``` + +启动成功后,API Server 默认监听 `http://0.0.0.0:9380`。 + +#### 验证后端服务 + +```bash +curl -s http://localhost:9380/v1/system/healthz +# 预期返回:健康检查通过的 JSON 响应 +``` + +#### 后端启动日志说明 + +正常启动时可能看到以下警告,属于预期行为: + +| 日志信息 | 说明 | +|---------|------| +| `term.freq is not supported` | OceanBase 的全文索引不支持词频特性,不影响功能 | +| `Realtime synonym is disabled, since no redis connection` | 未配置 Redis,同义词实时更新功能不可用 | +| `pthread_setaffinity_np failed` | ONNX Runtime 线程亲和性设置失败,无影响 | + +--- + +## 4. 前端部署 + +### 4.1 安装依赖 + +```bash +cd web +npm install +``` + +> **注意**:安装过程中会自动运行 Tailwind CSS 插件修复脚本(通过 `postinstall` 钩子),修复 UmiJS Tailwind 插件的已知问题。如果遇到 Tailwind CSS 生成失败,可手动运行: +> ```bash +> node scripts/fix-tailwindcss-plugin.js +> ``` + +### 4.2 启动前端开发服务器 + +```bash +cd web +npm run dev +``` + +前端开发服务器默认运行在 `http://localhost:9222`(通过 proxy 转发 API 请求到后端 9380 端口)。 + +--- + +## 5. 常见问题与解决方案 + +### Q1: `download_deps.py` 下载超时 + +**原因**:无法直接访问外部 URL(Maven、HuggingFace 等) + +**解决**:使用 `set_backend_deps.sh` 从 Docker 镜像复制依赖: + +```bash +docker pull infiniflow/ragflow_deps:latest +bash set_backend_deps.sh +``` + +--- + +### Q2: 连接 SeekDB 报 `Access denied` + +**原因**:密码不匹配或容器未完全启动 + +**解决**: +1. 确认容器状态:`docker ps --filter name=powerrag-seekdb` +2. 确认密码与启动参数一致:`ROOT_PASSWORD=powerrag` +3. 等待容器 healthcheck 通过后再连接 + +--- + +### Q3: 后端启动报 `peewee.OperationalError: (1049, "Unknown database 'powerrag'")` + +**原因**:数据库尚未创建 + +**解决**: + +```bash +mysql -h127.0.0.1 -P2881 -uroot -ppowerrag -e " + CREATE DATABASE IF NOT EXISTS powerrag; + CREATE DATABASE IF NOT EXISTS powerrag_doc; +" +``` + +--- + +### Q4: ONNX Runtime 报 `pthread_setaffinity_np failed` + +**原因**:某些容器化环境或受限 Linux 环境不支持线程亲和性设置 + +**解决**:此警告不影响功能,可忽略。 diff --git a/docs/developer-setup-guide.md b/docs/developer-setup-guide.md new file mode 100644 index 000000000..21ba60e02 --- /dev/null +++ b/docs/developer-setup-guide.md @@ -0,0 +1,255 @@ +# PowerRAG Source Code Deployment Guide + +> This guide documents the complete process of deploying PowerRAG from source code, using SeekDB (OceanBase) Docker container for the database, suitable for local development environments. + +--- + +## Table of Contents + +- [Quick Start](#quick-start) +- [1. Prerequisites](#1-prerequisites) +- [2. Database Deployment (SeekDB)](#2-database-deployment-seekdb) +- [3. Backend Deployment](#3-backend-deployment) +- [4. Frontend Deployment](#4-frontend-deployment) +- [5. Troubleshooting](#5-troubleshooting) + +--- + +## Quick Start + +Here are the quick reference commands for a complete deployment: + +```bash +# 1. Start SeekDB database +docker run -d --name powerrag-seekdb \ + -p 2881:2881 \ + -e ROOT_PASSWORD=powerrag \ + -e INIT_SCRIPTS_PATH=/root/boot/init.d \ + -v $(pwd)/docker/oceanbase/init.d:/root/boot/init.d \ + oceanbase/seekdb:1.0.0.0-100000262025111218 + +# 2. Wait for database to be ready & create databases +sleep 60 +mysql -h127.0.0.1 -P2881 -uroot -ppowerrag -e \ + "CREATE DATABASE IF NOT EXISTS powerrag; CREATE DATABASE IF NOT EXISTS powerrag_doc;" + +# 3. Install Python dependencies +uv sync --python 3.12 --all-extras + +# 4. Download models and NLP resources +docker pull infiniflow/ragflow_deps:latest +bash set_backend_deps.sh + +# 5. Start backend +source .venv/bin/activate +export PYTHONPATH=$(pwd) +bash docker/launch_backend_service.sh & + +# 6. Install frontend dependencies +cd web +npm install + +# 7. Start frontend +npm run dev & + +# 8. Access +# Frontend: http://localhost:9222 +# API: http://localhost:9380 +``` + +--- + +## 1. Prerequisites + +| Component | Version Requirement | Notes | +|-----------|-------------------|-------| +| **OS** | Linux (x86_64) | Tested on AlmaLinux 8 (kernel 5.10) | +| **Python** | ≥ 3.12, < 3.15 | Recommended 3.12.x | +| **uv** | ≥ 0.9.x | Python package manager | +| **Node.js** | ≥ 22.x | Frontend build | +| **npm** | ≥ 10.x | Frontend package manager | +| **Docker** | ≥ 20.x | For running SeekDB database | +| **Disk Space** | ≥ 50GB | Database + model files + dependencies | +| **Memory** | ≥ 16GB | SeekDB recommends 10GB+, application services 4GB+ | + +--- + +## 2. Database Deployment (SeekDB) + +### 2.1 Start SeekDB Container + +```bash +docker run -d \ + --name powerrag-seekdb \ + -p 2881:2881 \ + -e ROOT_PASSWORD=powerrag \ + -e INIT_SCRIPTS_PATH=/root/boot/init.d \ + -v $(pwd)/docker/oceanbase/init.d:/root/boot/init.d \ + oceanbase/seekdb:1.0.0.0-100000262025111218 +``` + +> **Notes**: +> - `ROOT_PASSWORD=powerrag`: Sets the database root password, must match the configuration in `conf/service_conf.yaml` +> - The initialization script `docker/oceanbase/init.d/vec_memory.sql` executes `ALTER SYSTEM SET ob_vector_memory_limit_percentage = 30;` to allocate memory for vector search +> - Port `2881` is OceanBase's MySQL protocol port + +### 2.2 Wait for Database to Be Ready + +SeekDB startup takes approximately 30-60 seconds. Verify with: + +```bash +# Check container health status +docker ps --filter name=powerrag-seekdb --format 'table {{.Names}}\t{{.Status}}' + +# Test connection +mysql -h127.0.0.1 -P2881 -uroot -ppowerrag -e "SELECT 1;" +``` + +### 2.3 Create Databases + +```bash +mysql -h127.0.0.1 -P2881 -uroot -ppowerrag -e " + CREATE DATABASE IF NOT EXISTS powerrag; + CREATE DATABASE IF NOT EXISTS powerrag_doc; +" +``` + +--- + +## 3. Backend Deployment + +### 3.1 Install Python Dependencies + +```bash +cd /path/to/powerrag +uv sync --python 3.12 --all-extras +``` + +> **Estimated Time**: First-time installation takes approximately 10-20 minutes (depending on network speed). + +### 3.2 Download Models and NLP Resources + +PowerRAG depends on multiple pre-trained models and NLP datasets. It's recommended to use the pre-built Docker image for quick access: + +```bash +# Pull the dependencies image first +docker pull infiniflow/ragflow_deps:latest + +# Execute the dependency copy script +bash set_backend_deps.sh +``` + +This script copies the following resources from the `infiniflow/ragflow_deps:latest` image: + +| Resource | Target Path | Purpose | +|----------|-------------|---------| +| HuggingFace Deep Document Models | `rag/res/deepdoc/` | Document layout analysis | +| XGBoost Text Concatenation Model | `rag/res/deepdoc/` | Text paragraph merging | +| BAAI/bge-large-zh-v1.5 | `~/.ragflow/` | Chinese vector embeddings | +| BCE Embedding | `~/.ragflow/` | Vector embeddings | +| NLTK Data | `nltk_data/` | Natural language processing | +| Tika Server | `tika-server-standard-3.0.0.jar` | Document parsing | +| tiktoken Encoding | `9b5ad71b2ce5302211f9c61530b329a4922fc6a4` | Token calculation | + +### 3.3 Start Backend Services + +```bash +source .venv/bin/activate +export PYTHONPATH=$(pwd) + +# Use the startup script (starts API Server, Task Executor, and Data Sync service) +bash docker/launch_backend_service.sh +``` + +After successful startup, the API Server listens on `http://0.0.0.0:9380` by default. + +#### Verify Backend Service + +```bash +curl -s http://localhost:9380/v1/system/healthz +# Expected: JSON response indicating health check passed +``` + +#### Backend Startup Log Notes + +The following warnings may appear during normal startup and are expected: + +| Log Message | Description | +|-------------|-------------| +| `term.freq is not supported` | OceanBase's full-text index doesn't support term frequency feature, doesn't affect functionality | +| `Realtime synonym is disabled, since no redis connection` | Redis not configured, real-time synonym update feature unavailable | +| `pthread_setaffinity_np failed` | ONNX Runtime thread affinity setting failed, no impact | + +--- + +## 4. Frontend Deployment + +### 4.1 Install Dependencies + +```bash +cd web +npm install +``` + +> **Note**: The installation process automatically runs the Tailwind CSS plugin fix script (via `postinstall` hook) to fix known issues with the UmiJS Tailwind plugin. If you encounter Tailwind CSS generation failures, you can manually run: +> ```bash +> node scripts/fix-tailwindcss-plugin.js +> ``` + +### 4.2 Start Frontend Development Server + +```bash +cd web +npm run dev +``` + +The frontend development server runs on `http://localhost:9222` by default (proxies API requests to backend port 9380). + +--- + +## 5. Troubleshooting + +### Q1: `download_deps.py` Download Timeout + +**Cause**: Unable to directly access external URLs (Maven Central, HuggingFace, etc.) + +**Solution**: Use `set_backend_deps.sh` to copy dependencies from Docker image: + +```bash +docker pull infiniflow/ragflow_deps:latest +bash set_backend_deps.sh +``` + +--- + +### Q2: SeekDB Connection Error `Access denied` + +**Cause**: Password mismatch or container not fully started + +**Solution**: +1. Check container status: `docker ps --filter name=powerrag-seekdb` +2. Verify password matches startup parameter: `ROOT_PASSWORD=powerrag` +3. Wait for container healthcheck to pass before connecting + +--- + +### Q3: Backend Startup Error `peewee.OperationalError: (1049, "Unknown database 'powerrag'")` + +**Cause**: Database not created yet + +**Solution**: + +```bash +mysql -h127.0.0.1 -P2881 -uroot -ppowerrag -e " + CREATE DATABASE IF NOT EXISTS powerrag; + CREATE DATABASE IF NOT EXISTS powerrag_doc; +" +``` + +--- + +### Q4: ONNX Runtime Error `pthread_setaffinity_np failed` + +**Cause**: Some containerized or restricted Linux environments don't support thread affinity settings + +**Solution**: This warning doesn't affect functionality and can be ignored. diff --git a/pyproject.toml b/pyproject.toml index a4899f01a..7f878d6ec 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,7 +45,7 @@ dependencies = [ "google-genai>=1.41.0,<2.0.0", "google-generativeai>=0.8.1,<0.9.0", # Needed for cv_model and embedding_model "google-search-results==2.4.2", - "graspologic @ git+https://github.com/yuzhichang/graspologic.git@38e680cab72bc9fb68a7992c3bcc2d53b24e42fd", + "graspologic>=3.4.5.dev2", "groq==0.9.0", "grpcio-status==1.67.1", "html-text==0.6.2", @@ -177,6 +177,7 @@ test = [ [[tool.uv.index]] url = "https://pypi.tuna.tsinghua.edu.cn/simple" +default = true [tool.setuptools] packages = [ diff --git a/uv.lock b/uv.lock index 127c682b8..ffb25e136 100644 --- a/uv.lock +++ b/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 2 +revision = 3 requires-python = ">=3.12, <3.15" resolution-markers = [ "python_full_version >= '3.14' and sys_platform == 'darwin'", @@ -13,6 +13,9 @@ resolution-markers = [ "(python_full_version < '3.13' and platform_machine != 'aarch64' and sys_platform == 'linux') or (python_full_version < '3.13' and sys_platform != 'darwin' and sys_platform != 'linux')", ] +[options] +prerelease-mode = "allow" + [[package]] name = "absl-py" version = "2.3.1" @@ -2657,8 +2660,8 @@ wheels = [ [[package]] name = "graspologic" -version = "0.1.dev847+g38e680cab" -source = { git = "https://github.com/yuzhichang/graspologic.git?rev=38e680cab72bc9fb68a7992c3bcc2d53b24e42fd#38e680cab72bc9fb68a7992c3bcc2d53b24e42fd" } +version = "3.4.5.dev2" +source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" } dependencies = [ { name = "anytree" }, { name = "beartype" }, @@ -2678,6 +2681,10 @@ dependencies = [ { name = "typing-extensions" }, { name = "umap-learn" }, ] +sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/cf/d9/3a20586ec6aa7097ea58e6b54a3b7170ae4445872f23d085460611b2a55b/graspologic-3.4.5.dev2.tar.gz", hash = "sha256:0226945c5e5ee31e1dec4e085f365577ab059e498ba842f455211fe35322c026", size = 6111760, upload-time = "2025-11-25T18:20:11.751Z" } +wheels = [ + { url = "https://pypi.tuna.tsinghua.edu.cn/packages/bf/d2/2752eeba482c6adb7697db70ad47c79c9c7f6ba030ff8bb30b1b1ef064ef/graspologic-3.4.5.dev2-py3-none-any.whl", hash = "sha256:eb1ec49fea530f04aa22ac40d5e89b8511141ea1c9e0d577816bbf1c20aade68", size = 5201199, upload-time = "2025-11-25T18:20:10.112Z" }, +] [[package]] name = "graspologic-native" @@ -6495,7 +6502,7 @@ requires-dist = [ { name = "google-genai", specifier = ">=1.41.0,<2.0.0" }, { name = "google-generativeai", specifier = ">=0.8.1,<0.9.0" }, { name = "google-search-results", specifier = "==2.4.2" }, - { name = "graspologic", git = "https://github.com/yuzhichang/graspologic.git?rev=38e680cab72bc9fb68a7992c3bcc2d53b24e42fd" }, + { name = "graspologic", specifier = ">=3.4.5.dev2" }, { name = "groq", specifier = "==0.9.0" }, { name = "grpcio-status", specifier = "==1.67.1" }, { name = "html-text", specifier = "==0.6.2" }, diff --git a/uv.toml b/uv.toml new file mode 100644 index 000000000..d6e5c5df1 --- /dev/null +++ b/uv.toml @@ -0,0 +1,3 @@ +# uv 加速配置 +# PyPI 下载镜像(清华源) +index-url = "https://pypi.tuna.tsinghua.edu.cn/simple" diff --git a/web/package.json b/web/package.json index 4331faf24..77936af21 100644 --- a/web/package.json +++ b/web/package.json @@ -5,7 +5,7 @@ "build": "umi build", "build-storybook": "storybook build", "dev": "cross-env UMI_DEV_SERVER_COMPRESS=none umi dev", - "postinstall": "umi setup", + "postinstall": "umi setup && node scripts/fix-tailwindcss-plugin.js", "lint": "umi lint --eslint-only", "prepare": "cd .. && husky web/.husky", "setup": "umi setup", diff --git a/web/scripts/fix-tailwindcss-plugin.js b/web/scripts/fix-tailwindcss-plugin.js new file mode 100755 index 000000000..eb6e7aec3 --- /dev/null +++ b/web/scripts/fix-tailwindcss-plugin.js @@ -0,0 +1,78 @@ +#!/usr/bin/env node + +/** + * 自动修复 UmiJS Tailwind CSS 插件的已知问题 + * 在 npm install 后自动运行(通过 postinstall 脚本) + */ + +const fs = require('fs'); +const path = require('path'); + +const PLUGIN_PATH = path.join( + __dirname, + '../node_modules/@umijs/plugins/dist/tailwindcss.js', +); + +function fixTailwindcssPlugin() { + if (!fs.existsSync(PLUGIN_PATH)) { + console.log('⚠️ Tailwind CSS plugin not found, skipping fix.'); + return; + } + + let content = fs.readFileSync(PLUGIN_PATH, 'utf8'); + let modified = false; + + // 修复 1: 超时时间从 5 秒增加到 60 秒 + if (content.includes('CHECK_TIMEOUT_UNIT_SECOND = 5')) { + content = content.replace( + /CHECK_TIMEOUT_UNIT_SECOND = 5/g, + 'CHECK_TIMEOUT_UNIT_SECOND = 60', + ); + modified = true; + console.log('✓ Fixed: Increased timeout from 5s to 60s'); + } else if (content.includes('CHECK_TIMEOUT_UNIT_SECOND = 60')) { + console.log('✓ Already fixed: Timeout is 60s'); + } + + // 修复 2: 确保输出目录存在 + const generatedDirCheck = + /const generatedDir = .*dirname.*generatedPath.*;\s*if \(!.*existsSync.*generatedDir.*\)/s; + if (!generatedDirCheck.test(content)) { + // 查找 generatedDir 定义的位置 + const dirPattern = + /(const generatedDir = \(0, import_path\.dirname\)\(generatedPath\);\s*)(const binPath)/s; + if (dirPattern.test(content)) { + content = content.replace( + dirPattern, + `$1if (!(0, import_fs.existsSync)(generatedDir)) {\n require("fs").mkdirSync(generatedDir, { recursive: true });\n }\n $2`, + ); + modified = true; + console.log('✓ Fixed: Added directory existence check'); + } + } else { + console.log('✓ Already fixed: Directory check exists'); + } + + // 修复 3: --watch 改为 --watch=always + if (content.includes('"--watch"') && !content.includes('"--watch=always"')) { + content = content.replace(/"--watch"/g, '"--watch=always"'); + modified = true; + console.log('✓ Fixed: Changed --watch to --watch=always'); + } else if (content.includes('"--watch=always"')) { + console.log('✓ Already fixed: Using --watch=always'); + } + + if (modified) { + fs.writeFileSync(PLUGIN_PATH, content, 'utf8'); + console.log('✅ Tailwind CSS plugin fixes applied successfully!'); + } else { + console.log('✅ All fixes already applied, no changes needed.'); + } +} + +try { + fixTailwindcssPlugin(); +} catch (error) { + console.error('❌ Error fixing Tailwind CSS plugin:', error.message); + process.exit(1); +}