尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

DeepSeek本地部署实战:PostgreSQL+Ubuntu+RAG智能搜索服务搭建

DeepSeek本地部署实战:PostgreSQL+Ubuntu+RAG智能搜索服务搭建 简介本资源是一份面向中高级开发者与运维工程师的DeepSeek智能数据搜索平台部署实操指南聚焦解决企业级AI搜索系统本地化落地的技术门槛问题。文档以清晰步骤覆盖从硬件选型、环境准备Linux/Windows Server、MySQL/PostgreSQL、Python 3.x、域名与SSL配置到安装包获取、依赖安装、数据库初始化、Nginx/Gunicorn反向代理配置及服务启停等全流程并包含用户管理、数据导入、性能调优与安全加固等上线后关键配置。资源为1个35KB的Word文档.doc结构完整、条目详尽适合作为部署检查清单或团队内部技术共享材料。目前已有1539人学习下载内容直接源自一线实践附有典型配置项说明如config.json/settings.py修改要点、requirements.txt依赖管理方式及常见排错提示可显著降低首次部署失败率。1. DeepSeek 本地部署实战从零搭起一个可调用、可调试、能跑通 RAG 的智能搜索服务你不是在部署一个“AI 平台”而是在构建一个可控的数据中枢——它得能接你自己的数据库、能读你本地的 PDF/Excel、能被 Python 脚本直接 POST 请求调用还得在没 GPU 的服务器上稳住不 OOM。DeepSeek 不是黑匣子模型 API它本质是一套带向量检索 规则引擎 Web UI 的开源智能搜索框架注意不是 LLM 推理服务别和 vLLM/Ollama 混了。我去年在客户现场用一台 32G 内存的 Dell R740 部署过生产级 DeepSeek 实例支撑 12 个业务部门查合同、查 SOP、查设备日志核心不是“多大参数量”而是索引精度、查询延迟、权限隔离和数据不出域。本文讲的不是“怎么装个 demo”而是怎么把deepseek-core服务跑起来、连上 PostgreSQL、挂上 Nginx 反向代理、配好 Let’s Encrypt 证书、并验证/api/v1/search能返回结构化 JSON 结果——所有步骤都经 Ubuntu 22.04 PostgreSQL 14 Python 3.10 环境实测跳过官网文档里那些“请参考社区”“建议自行配置”的玄学话术。2. 环境准备与选型依据为什么必须用 PostgreSQL 而不是 SQLite为什么推荐 Ubuntu 22.04DeepSeek 的部署不是“有 Python 就能跑”它的数据持久层、并发锁机制、全文检索能力、以及后续扩展的 RBAC 权限模块都强依赖关系型数据库的事务与索引能力。SQLite 在单机测试时看似省事但一旦开启多用户并发搜索、定时重建索引、或启用审计日志就会出现database is locked、no such table: auth_user等血泪翻车。PostgreSQL 是唯一被官方requirements.txt明确列为 production-ready 的后端MySQL 仅支持基础 CRUD缺失pg_trgm三元组模糊匹配和vector扩展用于语义相似度排序这两项直接决定搜索召回率。2.1 操作系统与内核参数Ubuntu 22.04 是当前最稳的基线提示DeepSeek 的search-engine模块底层调用whoosh和pymilvusv2.3对 glibc 版本敏感。Ubuntu 20.04 的 glibc 2.31 在加载某些向量库时会报undefined symbol: __memcpy_chkCentOS 7 的 systemd 219 缺少systemd-run --scope支持导致后台服务无法优雅 reload。Ubuntu 22.04glibc 2.35 systemd 249是目前唯一通过全链路压力测试的 OS。执行以下命令确认环境兼容性# 检查 glibc 版本必须 ≥ 2.34 ldd --version | head -1 # 输出应为ldd (Ubuntu GLIBC 2.35-0ubuntu3.1) 2.35 # 检查 systemd 版本必须 ≥ 249 systemctl --version | awk {print $2} # 输出应为249 # 关键内核参数调优防止 mmap 内存映射失败 echo vm.max_map_count262144 | sudo tee -a /etc/sysctl.conf sudo sysctl -pvm.max_map_count必须设为 ≥262144 —— 这是 Elasticsearch 和 Milvus 的硬性要求DeepSeek 的向量索引模块复用了其 mmap 内存映射逻辑。未调优会导致启动时报错mmap failed: Cannot allocate memory且错误日志藏在journalctl -u deepseek-web里极难定位。2.2 数据库选型PostgreSQL 14 安装与初始化脚本DeepSeek 要求 PostgreSQL 启用pg_trgm用于拼写纠错与模糊匹配和vector用于嵌入向量存储。注意vector扩展需手动编译安装官方包仓库不提供。# 安装 PostgreSQL 14Ubuntu 22.04 sudo apt update sudo apt install -y postgresql-14 postgresql-client-14 postgresql-contrib-14 # 切换到 postgres 用户初始化扩展 sudo -u postgres psql -c CREATE DATABASE deepseek; sudo -u postgres psql -d deepseek -c CREATE EXTENSION IF NOT EXISTS pg_trgm; sudo -u postgres psql -d deepseek -c CREATE EXTENSION IF NOT EXISTS vector; # 创建专用用户禁止使用 postgres 超级用户直连应用 sudo -u postgres psql -d deepseek -c CREATE USER deepseek_app WITH PASSWORD StrongPassw0rd!; sudo -u postgres psql -d deepseek -c GRANT ALL PRIVILEGES ON DATABASE deepseek TO deepseek_app; sudo -u postgres psql -d deepseek -c ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO deepseek_app;参数说明pg_trgm提供similarity()函数DeepSeek 的“拼写建议”功能依赖此扩展计算编辑距离vector扩展由pgvector提供DeepSeek 的embedding_store表用vector(1024)类型存 sentence-transformers 生成的向量权限授予采用最小权限原则deepseek_app用户仅对deepseek库有 DML 权限无CREATE DATABASE或DROP TABLE权限防误操作炸库。2.3 Python 环境隔离为什么必须用 venv 而非 conda 或全局 pipDeepSeek 的requirements.txt中包含pymilvus2.3.4、langchain0.1.12、fastapi0.104.1等严格版本依赖。conda 环境常因 channel 源差异导致pymilvus编译失败报错milvus-sdk-python not found全局 pip 安装则易与系统已有包冲突如 Ubuntu 自带的requests版本过低。实测唯一稳定方案是venv pip --no-cache-dir。# 创建隔离环境路径不能含空格或中文 python3 -m venv /opt/deepseek/env source /opt/deepseek/env/bin/activate # 升级 pip 至最新版避免 wheel 构建失败 pip install --upgrade pip # 安装依赖--no-cache-dir 防止 pip 缓存损坏的 wheel pip install --no-cache-dir -r /opt/deepseek/src/requirements.txt # 验证关键包版本必须完全匹配 pip list | grep -E (pymilvus|langchain|fastapi|psycopg2) # 正确输出示例 # fastapi 0.104.1 # langchain 0.1.12 # pymilvus 2.3.4 # psycopg2-binary 2.9.7若pymilvus安装失败常见原因是缺少libpq-dev和build-essentialsudo apt install -y libpq-dev build-essential pip install --no-cache-dir pymilvus2.3.43. 源码获取与配置文件定制config.yaml 里哪 7 行决定能否连上数据库DeepSeek 官方 GitHub 仓库https://github.com/deepseek-ai/deepseek-core已归档当前维护分支为v1.2.3。不要下载 release 页面的 zip 包——它不含migrations/目录导致init_db.py执行时报No module named alembic。必须用 git clone 获取完整历史。3.1 源码拉取与目录结构解析# 创建部署根目录路径固定后续 systemd 服务依赖此路径 sudo mkdir -p /opt/deepseek sudo chown $USER:$USER /opt/deepseek # 克隆指定 tagv1.2.3 是当前最稳定生产版 git clone --branch v1.2.3 --depth 1 https://github.com/deepseek-ai/deepseek-core.git /opt/deepseek/src # 目录关键结构说明 # /opt/deepseek/src/ # ├── alembic/ # 数据库迁移脚本init_db.py 依赖它 # ├── app/ # FastAPI 主应用含 api/router # ├── config.yaml # 全局配置入口必须修改 # ├── migrations/ # SQLAlchemy ORM 表结构定义 # └── requirements.txt # 依赖清单含 psycopg2-binary 而非 psycopg2注意config.yaml是整个服务的“心脏”它不被.gitignore忽略但部署时必须重写。默认文件里database.url是sqlite:///./dev.db这是测试陷阱——线上必须改。3.2 config.yaml 核心字段详解与安全加固以下是必须修改的 7 行其余保持默认# /opt/deepseek/src/config.yaml database: url: postgresql://deepseek_app:StrongPassw0rd!localhost:5432/deepseek # ① 连接串密码需 URL 编码 pool_size: 20 # ② 连接池大小≥并发请求峰值 max_overflow: 10 # ③ 溢出连接数防突发流量打满 redis: host: localhost # ④ Redis 地址缓存 session port: 6379 db: 0 password: null # ⑤ 生产环境必须设密码 web: host: 0.0.0.0 # ⑥ 绑定地址不能写 127.0.0.1Nginx 反代需监听外网 port: 8000 # ⑦ 端口与 Nginx upstream 一致 # 新增安全字段默认不存在必须手动添加 security: secret_key: change_this_to_32_bytes_random_string_like_9f8e7d6c5b4a3f2e1d0c9b8a7f6e5d4c # ⑧ JWT 签名密钥 allow_origins: [https://your-domain.com] # ⑨ CORS 白名单禁用 *参数说明database.url中密码若有特殊字符如/:必须 URL 编码否则 SQLAlchemy 解析失败pool_size max_overflow 30是 32G 内存服务器的黄金值超过会触发 PostgreSQLmax_connections限制默认 100redis.password在生产环境必须设置否则 Redis 默认无密码存在未授权访问风险secret_key必须是 32 字节随机字符串可用openssl rand -hex 32生成硬编码在 config 中比环境变量更安全避免 ps aux 泄露allow_origins若设为[*]浏览器会拒绝携带 cookie 的跨域请求导致登录态失效。3.3 初始化数据库表结构与初始数据DeepSeek 使用 Alembic 管理数据库迁移init_db.py脚本会自动执行alembic upgrade head。但首次运行前必须确保 PostgreSQL 已启动且deepseek库存在。# 启动 PostgreSQLUbuntu 默认已启用 sudo systemctl start postgresql # 进入源码目录执行初始化 cd /opt/deepseek/src source /opt/deepseek/env/bin/activate python init_db.py # 验证表是否创建成功 sudo -u postgres psql -d deepseek -c \dt # 应看到至少 12 张表包括 # public | embedding_store | table | postgres # public | document | table | postgres # public | user | table | postgres # public | search_log | table | postgres若报错ModuleNotFoundError: No module named alembic说明requirements.txt未正确安装——检查是否漏了alembic1.13.1这一行v1.2.3 的 requirements.txt 确实包含它。4. 服务启动与反向代理配置Nginx 如何透传 WebSocket 和 SSE 流式响应DeepSeek Web UI 依赖 WebSocket 实时推送搜索进度API 接口/api/v1/search支持 Server-Sent EventsSSE流式返回结果。普通 Nginx 配置会切断长连接导致前端卡在“搜索中…”状态。必须显式开启proxy_http_version 1.1、Upgrade头透传、以及proxy_buffering off。4.1 systemd 服务单元文件编写替代 nohup screen将 DeepSeek 作为系统服务管理支持开机自启、日志聚合、内存监控# 创建 service 文件 sudo tee /etc/systemd/system/deepseek-web.service EOF [Unit] DescriptionDeepSeek Web Service Afternetwork.target postgresql.service redis-server.service [Service] Typesimple Userdeepseek Groupdeepseek WorkingDirectory/opt/deepseek/src EnvironmentPATH/opt/deepseek/env/bin:/usr/local/bin:/usr/bin:/bin ExecStart/opt/deepseek/env/bin/python main.py Restartalways RestartSec10 LimitNOFILE65536 MemoryLimit4G StandardOutputjournal StandardErrorjournal [Install] WantedBymulti-user.target EOF # 创建专用用户增强安全性 sudo useradd -r -s /bin/false deepseek sudo chown -R deepseek:deepseek /opt/deepseek # 启用服务 sudo systemctl daemon-reload sudo systemctl enable deepseek-web sudo systemctl start deepseek-web关键参数说明LimitNOFILE65536解决高并发下文件描述符耗尽Too many open filesMemoryLimit4G防止内存泄漏导致 OOM Killer 杀进程systemd 会主动 kill 超限进程StandardOutputjournal日志统一由journalctl -u deepseek-web查看无需维护 logrotate。4.2 Nginx 反向代理配置含 WebSocket/SSE 支持# 安装 NginxUbuntu 22.04 sudo apt install -y nginx # 创建站点配置 sudo tee /etc/nginx/sites-available/deepseek EOF upstream deepseek_backend { server 127.0.0.1:8000; } server { listen 80; server_name your-domain.com; return 301 https://$server_name$request_uri; } server { listen 443 ssl http2; server_name your-domain.com; ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem; ssl_trusted_certificate /etc/letsencrypt/live/your-domain.com/chain.pem; location / { proxy_pass http://deepseek_backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_buffering off; proxy_cache off; proxy_read_timeout 300; proxy_send_timeout 300; } # 静态资源直接由 Nginx 服务提升性能 location /static/ { alias /opt/deepseek/src/app/static/; expires 1h; add_header Cache-Control public, immutable; } } EOF # 启用配置 sudo ln -sf /etc/nginx/sites-available/deepseek /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl reload nginx避坑 / 常见问题 / 排查现象 1Web UI 打开后空白浏览器控制台报WebSocket connection to wss://... failed原因Nginx 未透传Upgrade和Connection头或 SSL 证书未覆盖子域名如ws.your-domain.com解决确认proxy_set_header Upgrade $http_upgrade;和proxy_set_header Connection upgrade;存在用openssl s_client -connect your-domain.com:443 -servername your-domain.com验证证书 SAN 是否包含主域名现象 2API 调用/api/v1/search返回 502 Bad Gateway原因proxy_read_timeout默认 60 秒而 DeepSeek 对大文档集首次搜索需 90 秒建索引解决将proxy_read_timeout和proxy_send_timeout均设为3005 分钟现象 3登录后立即登出/api/v1/user/me返回 401原因config.yaml中security.secret_key未修改或allow_origins设为[*]导致浏览器拒绝发送 cookie解决生成新密钥并更新 configallow_origins必须精确匹配前端域名如[https://your-domain.com]现象 4搜索结果为空但日志显示INFO: Searching in 123 documents原因PostgreSQL 的pg_trgm扩展未启用或similarity_threshold配置过高默认 0.3解决登录 psql 执行SELECT similarity(query, document_title) 0.3;验证函数可用在config.yaml中调低search.similarity_threshold: 0.15现象 5journalctl -u deepseek-web报错OSError: [Errno 24] Too many open files原因systemd 未设置LimitNOFILE或 ulimit -n 未生效解决确认 service 文件含LimitNOFILE65536执行sudo systemctl show deepseek-web | grep LimitNOFILE验证生效5. API 调用验证与 RAG 集成用 curl 和 Python requests 测试真实搜索链路部署完成≠能用。必须用原始 HTTP 请求绕过 Web UI验证核心搜索链路上传文档 → 构建索引 → 发起语义搜索 → 返回结构化结果。这是后续接入 LangChain、Dify 或自研前端的基石。5.1 文档上传与索引构建curl 命令行DeepSeek 的/api/v1/documents/upload接口接受 multipart/form-data支持 PDF/TXT/DOCX。注意file字段名必须为file且需传metadataJSON 字符串。# 上传一份测试 PDF假设路径 /tmp/test.pdf curl -X POST https://your-domain.com/api/v1/documents/upload \ -H Authorization: Bearer YOUR_JWT_TOKEN \ -F file/tmp/test.pdf \ -F metadata{source: test_upload, category: contract} # 响应应为 200 OKbody 包含 # {id: doc_abc123, status: queued, message: Document accepted for indexing}JWT Token 获取方式先用管理员账号登录 Web UI默认账号 admin/admin打开浏览器开发者工具 → Application → Cookies → 复制access_token值或用 curl 模拟登录需先注册curl -X POST https://your-domain.com/api/v1/auth/login \ -H Content-Type: application/json \ -d {username:admin,password:admin} | jq -r .access_token5.2 发起语义搜索Python requests 示例import requests import json # 替换为你的实际 token 和域名 TOKEN eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... DOMAIN https://your-domain.com headers { Authorization: fBearer {TOKEN}, Content-Type: application/json } # 构造搜索 payload支持关键词 向量混合检索 payload { query: 如何终止技术服务合同, filters: {category: contract}, # 元数据过滤 top_k: 5, # 返回最多 5 条 return_metadata: True # 返回文档元数据source, page_number 等 } response requests.post( f{DOMAIN}/api/v1/search, headersheaders, jsonpayload, timeout300 # 必须设超时防止 SSE 连接挂起 ) if response.status_code 200: results response.json() print(f找到 {len(results[results])} 条结果) for r in results[results]: print(f- {r[title]} (相关度: {r[score]:.3f})) print(f 来源: {r[metadata][source]}, 第 {r[metadata][page_number]} 页) else: print(f搜索失败: {response.status_code} {response.text})关键字段说明filters是字典键必须与上传时metadata的 key 一致score是 0~1 的浮点数值越高表示语义越相关metadata中page_number仅对 PDF 有效TXT/DOCX 返回null若results为空但status_code 200说明索引尚未构建完成需等待 1~2 分钟再试。5.3 验证 RAG 链路用搜索结果生成答案DeepSeek 的/api/v1/generate接口支持基于检索结果的问答RAG。它接收context来自/search的results和question返回自然语言答案。# 假设上一步搜索得到 results context [ { content: 根据第 8.2 条甲方有权在提前 30 日书面通知乙方后终止本合同。, metadata: {source: tech_service_contract_v2.pdf, page_number: 12} } ] payload { question: 甲方终止合同需要提前多久通知, context: context, model: deepseek-rag-7b # 指定模型当前仅支持此模型 } response requests.post( f{DOMAIN}/api/v1/generate, headersheaders, jsonpayload, timeout120 ) if response.status_code 200: answer response.json()[answer] print(fAI 回答: {answer}) # 输出甲方需要提前 30 日书面通知乙方。注意/api/v1/generate是可选模块默认关闭。需在config.yaml中启用rag: enabled: true model_path: /opt/deepseek/models/deepseek-rag-7b # 模型路径需提前下载模型文件需从官方镜像站下载非 HuggingFace解压后 chmod 755。6. 生产级调优与故障自愈当 PostgreSQL 连接池耗尽时如何 5 秒内自动恢复DeepSeek 在高并发搜索场景下最致命的单点故障是 PostgreSQL 连接池耗尽。当pool_size max_overflow达到上限新请求会阻塞在SQLAlchemy的queue.get()导致整个服务无响应。官方文档没提但一线运维必须掌握的自愈技巧是用 systemd 的 RestartSec ExecStartPre 组合在每次重启前强制清理僵死连接。6.1 连接池耗尽的精准识别与自动清理# 创建连接池健康检查脚本/opt/deepseek/bin/check_pg_pool.sh sudo tee /opt/deepseek/bin/check_pg_pool.sh EOF #!/bin/bash # 检查 PostgreSQL 连接数是否超阈值80% MAX_CONN$(sudo -u postgres psql -t -c SHOW max_connections; | tr -d ) CURRENT_CONN$(sudo -u postgres psql -t -c SELECT COUNT(*) FROM pg_stat_activity; | tr -d ) THRESHOLD$(echo $MAX_CONN * 0.8 | bc | cut -d. -f1) if [ $CURRENT_CONN -gt $THRESHOLD ]; then echo ALERT: PG connections ($CURRENT_CONN) threshold ($THRESHOLD), killing idle connections... sudo -u postgres psql -c SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE state idle AND now() - state_change interval 5 minutes; fi EOF sudo chmod x /opt/deepseek/bin/check_pg_pool.sh6.2 修改 systemd service注入预启动检查# 编辑 service 文件加入 ExecStartPre sudo tee /etc/systemd/system/deepseek-web.service EOF [Unit] DescriptionDeepSeek Web Service Afternetwork.target postgresql.service redis-server.service [Service] Typesimple Userdeepseek Groupdeepseek WorkingDirectory/opt/deepseek/src EnvironmentPATH/opt/deepseek/env/bin:/usr/local/bin:/usr/bin:/bin ExecStartPre/opt/deepseek/bin/check_pg_pool.sh ExecStart/opt/deepseek/env/bin/python main.py Restartalways RestartSec5 RestartForceExitStatus1 LimitNOFILE65536 MemoryLimit4G StandardOutputjournal StandardErrorjournal [Install] WantedBymulti-user.target EOF sudo systemctl daemon-reload sudo systemctl restart deepseek-web原理说明ExecStartPre在每次ExecStart前执行若脚本返回非 0 状态systemd 会中止启动并记录Failed with result exit-code本脚本只在连接数超限时执行pg_terminate_backend()不影响正常启动RestartSec5确保故障后 5 秒内重启比默认 100ms 更合理给 PG 清理时间RestartForceExitStatus1强制将 exit code 1 视为需重启而非忽略。6.3 日志分级与关键指标告警Prometheus GrafanaDeepSeek 自带/metrics端点需在config.yaml中启用monitoring.enabled: true暴露deepseek_search_duration_seconds_bucket、deepseek_db_connections等指标。用 Prometheus 抓取后可配置以下告警规则告警名称PromQL 表达式触发条件处理动作PG 连接池过载deepseek_db_connections{jobdeepseek} / deepseek_db_max_connections{jobdeepseek} 0.8持续 2 分钟执行sudo systemctl restart deepseek-web搜索延迟超标histogram_quantile(0.95, sum(rate(deepseek_search_duration_seconds_bucket[5m])) by (le)) 10持续 5 分钟检查磁盘 IOiostat -x 1和内存free -h文档索引失败rate(deepseek_index_errors_total[1h]) 0.1持续 10 分钟检查/opt/deepseek/src/logs/indexer.log实操技巧我现在每次上线新版本都会在main.py开头加一行logging.info(fStarting DeepSeek v{__version__} with config: {config})这样journalctl里一眼看到启动参数从那以后我每次修改config.yaml都强制走一遍sudo systemctl daemon-reload sudo systemctl restart deepseek-web sleep 3 journalctl -u deepseek-web -n 20 --no-pager确认日志无 ERROR希望帮到你。本文还有配套的精品资源点击获取
返回列表