# 服务器部署 ## Linux 首次部署 准备项目代码(包含 pyproject.toml、uv.lock、.python-version、src、scripts、html、deploy.sh)、可读取的 metadata 模板及 relation.xlsx;确认 Neo4j、Redis、DMS 和 DeepSeek 可用。 ```bash # 首次创建;已有 .env 时跳过,避免覆盖 [ -f .env ] || cp .env.example .env # 编辑 .env 中的真实连接配置、监听地址、模板及模型目录 sh deploy.sh templates ``` 该命令完成 uv 安装(缺失时)、Python 安装、锁定依赖同步、模型下载/验证、模板与数据更新、版本发布、服务启动。uv 自动安装到项目 `.runtime/bin`,不改 shell 配置;已有 PATH 或 ~/.local/bin 中的 uv 优先使用。 环境安装依据 [uv 官方安装说明](https://docs.astral.sh/uv/configuration/installer/) 和 [Python 管理说明](https://docs.astral.sh/uv/guides/install-python/)。项目依赖按 uv.lock 同步,不重新生成锁文件。 ## 从旧版 Python 3.11 部署升级 更新代码时一并上传 `.python-version`,然后重新执行 `sh deploy.sh templates`。脚本会通过 uv 安装 Python 3.14.5 并同步项目虚拟环境;不需要修改系统 Python。若服务器曾设置 `DEPLOY_PYTHON=3.11`,先执行 `unset DEPLOY_PYTHON`,或显式运行 `DEPLOY_PYTHON=3.14.5 sh deploy.sh templates`。已有服务应先停止再执行模板更新。 `SyntaxError: f-string expression part cannot include a backslash` 来自旧代码在 f-string 表达式内转义 Markdown 竖线,该写法不兼容 Python 3.11。现已将转义移到表达式外,保持报告内容不变。 ## 操作选择 | 命令 | 作用 | |---|---| | `sh deploy.sh setup` | 只准备环境和模型,不操作业务数据或启动服务 | | `sh deploy.sh model` | 确保环境和模型就绪;完整模型不重复下载 | | `sh deploy.sh templates` | 准备环境和模型 → 模板更新 → 自动启动 | | `sh deploy.sh dms` | 准备环境和模型 → 数据更新 → 自动启动,要求已有模板基线 | | `sh deploy.sh start` | 准备环境和模型 → 启动已发布版本 | | `sh deploy.sh restart` | 准备完成后优雅停止本项目受管服务,加载新代码启动;不更新业务数据 | 不传参数默认执行 templates。可追加 `--host 0.0.0.0 --port 8000` 覆盖监听配置(setup/model 不接受监听参数)。服务前台运行,Ctrl+C 停止;没有后台 PID 管理、自动杀进程或开机自启。替换代码后使用 `sh deploy.sh restart`;templates/dms 更新前仍需先停止旧实例。 ## .env 配置示例 ```dotenv SERVICE_HOST=0.0.0.0 SERVICE_PORT=8000 METADATA_TEMPLATE_DIR=/srv/knowledge-data/metadata RELATION_DIR=/srv/knowledge-data/relations EMBEDDING_MODEL_DIR=/srv/knowledge-data/models/Qwen3-Embedding-0.6B EMBEDDING_MODEL_REPO=Qwen/Qwen3-Embedding-0.6B EMBEDDING_MODEL_SOURCE=modelscope ``` 还需填写 .env.example 中列出的数据库、Redis、DMS 和模型服务凭据。目录相对值以项目根为基准;进程环境优先于 .env。模板目录必须存在且可读;关系文件固定为 RELATION_DIR/relation.xlsx。模型目录允许自动创建,运行账号需有写入权限。下载和 Step2/Step3 编码器共用 EMBEDDING_MODEL_DIR,运行编码器仅加载本地文件。 ## 下载与安装控制 默认下载 [Qwen 官方 ModelScope 模型](https://www.modelscope.cn/models/Qwen/Qwen3-Embedding-0.6B)。ModelScope 下载依赖由 uv 的临时环境提供,不加入项目锁文件。设置 EMBEDDING_MODEL_SOURCE=huggingface 可改用 Hugging Face;两个来源使用各自的 EMBEDDING_MODEL_REPO 仓库标识,切换其他模型时请使用新的模型目录,避免复用旧权重。 模型检查包含配置、分片文件和本地实际加载/编码。中断下载可重新执行;已完整且可加载时不会联网下载。只检查本地文件: ```bash uv run --frozen python scripts/download_model.py --check-only # 文件损坏时重新调用下载器修复;保留现有目录,不执行删除 uv run --frozen python scripts/download_model.py --force ``` 以下变量在 shell 中设置(不从 .env 读取),示例: ```bash AUTO_INSTALL_UV=0 DEPLOY_PYTHON=3.14.5 sh deploy.sh setup UV_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple sh deploy.sh setup ``` AUTO_INSTALL_UV 默认 1;设为 0 时缺 uv 会报错。DEPLOY_PYTHON 未设置时读取项目 `.python-version`(3.14.5),与本地开发版本保持一致;安装、同步和各运行步骤均显式使用选定版本。UV_CACHE_DIR 默认项目 .uv-cache。uv 自身安装需 curl 或 wget 以及到官方安装地址的网络;Python、依赖和模型下载需对应网络访问与磁盘空间。脚本不会执行 .env 中的 shell 表达式。 ## Windows 本地测试直接在 PowerShell 中执行,无需 Git Bash: ```powershell uv sync --frozen if ($LASTEXITCODE -ne 0) { throw "环境安装失败" } uv run --frozen python scripts/download_model.py if ($LASTEXITCODE -ne 0) { throw "模型准备失败" } uv run --frozen python scripts/update_data.py --mode templates if ($LASTEXITCODE -ne 0) { throw "模板更新失败" } uv run --frozen python scripts/start_service.py ``` 日常数据更新将 `--mode templates` 改为 `--mode dms`;仅启动直接执行最后一行,代码替换后重启添加 `--restart`。README 的 [Windows 本地测试](../README.md#windows-本地测试powershell无需-git-bash) 提供分别可复制的操作块。更新前先停止旧服务,命令沿用 `.env` 中的路径及监听配置。 Windows 中路径可写为 D:/knowledge-data/...,现有模型可复用;不要把 Windows 的 .venv 复制到 Linux。Linux 部署继续使用 deploy.sh。 ## 失败恢复与验证边界 环境或模型准备失败时,不运行更新或服务;缺 .env 时创建示例并提示填写,不直接以示例配置更新。更新失败不会启动;更新成功但启动失败,已发布版本保留,修复端口/连接问题后执行 start 即可。端口被占用时先确认并停止旧实例。 启动脚本会打印浏览器访问地址。服务在 `0.0.0.0` 监听时,本机访问 `http://127.0.0.1:端口/`,同事访问启动时打印的局域网地址;`0.0.0.0` 本身不能用于浏览器访问。局域网 IP 可能随 DHCP 变化,同事连接同一局域网并确保防火墙放行相应端口。 已完成离线编排测试及当前 Windows 本地模型加载/编码验证;Linux 新机安装、联网模型下载及真实业务部署需在目标服务器验收。 ### 替换代码后重启 ```bash sh deploy.sh restart # 也可覆盖新实例的监听参数 sh deploy.sh restart --host 0.0.0.0 --port 8000 ``` 先完成环境、配置及模型检查,再请求旧服务优雅退出,最多等待30秒;退出后启动新实例,不执行模板或数据更新。没有受管服务时直接启动。重复start会拒绝启动第二个受管实例。 服务持有 `.runtime/service.lock`,通过 `.runtime/service-control.json` 中的随机凭据连接本机控制通道;仅请求本项目服务退出,不按端口杀进程。超时或身份确认失败会报错,不强制结束进程或启动新实例。正常退出会清理控制信息。 首次升级到此版本时,已运行的旧服务没有管理记录,需要在原终端按 Ctrl+C 停止一次;之后通过此入口启动的服务均可restart。若其他程序占用端口,仍需手动处理。服务继续前台运行;新实例启动失败时旧服务不会自动恢复。