智能问答系统(chat_py)技术架构与部署文档
本文档仅针对
chat_py_server(后端)与chat_py_front(前端)两个项目。
1. 项目简述
本系统是一个基于 大语言模型 + LangGraph 多智能体编排 + RAG 知识库检索 的智能问答平台,面向企业招商/政策等业务场景。
核心能力:
- 多轮对话:支持会话记忆与上下文指代消解(如"这个公司""再帮我查一下")。
- 主管智能体编排:由主管(Supervisor)分析用户问题,自动选择并调度多个子智能体工具。
- 子智能体工具:日历、天气、联网搜索、知识库检索、系统页面推荐、企业查找、企业详情、企业经营分析、报表生成等。
- 技能(Skill)选择:前端可手动指定"企业详情 / 知识库查询 / 联网搜索"技能,强制主管走对应子智能体。
- 登录鉴权:用户名密码 + 图形验证码登录,BCrypt 密码校验 + JWT Token,基于 MySQL 数据源连接池与 Redis 验证码缓存。
- 报表与图表:后端生成 Excel 报表并提供下载链接,同时输出 ECharts 图表配置,前端直接渲染图表。
- 知识库:文档上传 → 文本切割 → 向量化 → Milvus 向量检索。
2. 项目目录结构
text
my-langchain/
├── chat_py_server/ # 后端(FastAPI + LangGraph)
│ ├── app.py # 服务入口(uvicorn 启动,监听 5020)
│ ├── requirements.txt # Python 依赖清单
│ ├── .env # 环境配置(数据库/模型/密钥等)
│ ├── Dockerfile # 后端应用镜像(FROM 基础镜像,只 COPY 源码)
│ ├── Dockerfile.base # 后端基础镜像(安装 Python 依赖,可复用)
│ ├── .dockerignore # 构建忽略项(排除 .env/数据/缓存等)
│ ├── docker-compose.yml # 后端编排
│ ├── docker-compose-milvus.yml # Milvus 编排(etcd + minio + milvus)
│ └── app/
│ ├── config/ # 配置类 settings.py
│ ├── controller/ # 控制层(chat/doc/auth)
│ ├── graph/ # LangGraph 主管编排(supervisor_graph、agent_descriptions)
│ ├── service/ # 业务服务(model/system)
│ │ ├── model/ # RAG/网站推荐等模型服务
│ │ └── system/ # milvus/embedding/redis/db/auth/oauth/conversation
│ ├── tools/ # 各子智能体工具(web/rag/weather/company 等)
│ ├── entity/ # 请求/响应实体(vo)
│ ├── model/ # OpenAI 客户端(deepseek / llm)
│ ├── utils/ # 公共工具(验证码、加密等)
│ └── skills/ # 技能定义(company-detail / rag / web-search)
│
└── chat_py_front/ # 前端(Vue3 + Vite)
├── package.json
├── vite.config.js # 开发代理 /chat_py_server -> 5020
├── .env.development # 开发环境 VITE_API_BASE(默认空,走代理)
└── src/
├── api/ # axios 封装 + 接口(auth/chat/request)
├── views/ # 页面(Login.vue / Chat.vue)
├── components/ # 会话列表等组件
├── store/ # Pinia(用户 token)
├── router/ # 路由守卫
└── utils/ # markdown 渲染、echarts 渲染
3. 所用技术栈
3.1 后端(chat_py_server)
| 类别 | 技术 | 说明 |
|---|---|---|
| Web 框架 | FastAPI / Uvicorn | 提供 REST + SSE 流式接口 |
| 编排框架 | LangGraph | 主管智能体多轮迭代编排、checkpointer 会话记忆 |
| LLM 接入 | OpenAI SDK | 接入 DeepSeek 及内部 LLM |
| 向量数据库 | Milvus + PyMilvus | 知识库/网站页面向量检索 |
| Embedding | sentence-transformers + bge-base-zh-v1.5 | 文本向量化(本地 CPU 推理) |
| 数据库 | SQLAlchemy + PyMySQL | 登录鉴权(用户表,连接池) |
| 缓存 | Redis | 图形验证码缓存 |
| 鉴权 | bcrypt + PyJWT | 密码校验 + JWT 签发/解析 |
| 验证码 | Pillow | 图形验证码生成 |
| 报表 | openpyxl | 生成 Excel 报表 |
| 文档解析 | PyPDF2 / langchain-text-splitters | PDF 读取、文本切割 |
| 日志 | loguru | 日志输出 |
| 部署 | Docker | 后端容器化 |
3.2 前端(chat_py_front)
| 类别 | 技术 |
|---|---|
| 框架 | Vue 3(Composition API) |
| 构建 | Vite |
| UI 组件 | Element Plus |
| 状态管理 | Pinia |
| 路由 | Vue Router |
| HTTP | Axios + fetch(SSE 流式) |
| Markdown | marked + DOMPurify |
| 图表 | ECharts |
3.3 中间件 / 基础设施
| 组件 | 说明 |
|---|---|
| MySQL | 用户登录鉴权(sys_user 表) |
| Redis | 图形验证码缓存 |
| Milvus | 向量检索(知识库、网站页面) |
| Nginx | 前端静态托管 + 后端反向代理(生产环境) |
4. 架构设计
4.1 总体架构
#mermaid-svg-3h1oYNQLLUj7gEkV{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-3h1oYNQLLUj7gEkV .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-3h1oYNQLLUj7gEkV .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-3h1oYNQLLUj7gEkV .error-icon{fill:#552222;}#mermaid-svg-3h1oYNQLLUj7gEkV .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-3h1oYNQLLUj7gEkV .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-3h1oYNQLLUj7gEkV .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-3h1oYNQLLUj7gEkV .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-3h1oYNQLLUj7gEkV .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-3h1oYNQLLUj7gEkV .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-3h1oYNQLLUj7gEkV .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-3h1oYNQLLUj7gEkV .marker{fill:#333333;stroke:#333333;}#mermaid-svg-3h1oYNQLLUj7gEkV .marker.cross{stroke:#333333;}#mermaid-svg-3h1oYNQLLUj7gEkV svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-3h1oYNQLLUj7gEkV p{margin:0;}#mermaid-svg-3h1oYNQLLUj7gEkV .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-3h1oYNQLLUj7gEkV .cluster-label text{fill:#333;}#mermaid-svg-3h1oYNQLLUj7gEkV .cluster-label span{color:#333;}#mermaid-svg-3h1oYNQLLUj7gEkV .cluster-label span p{background-color:transparent;}#mermaid-svg-3h1oYNQLLUj7gEkV .label text,#mermaid-svg-3h1oYNQLLUj7gEkV span{fill:#333;color:#333;}#mermaid-svg-3h1oYNQLLUj7gEkV .node rect,#mermaid-svg-3h1oYNQLLUj7gEkV .node circle,#mermaid-svg-3h1oYNQLLUj7gEkV .node ellipse,#mermaid-svg-3h1oYNQLLUj7gEkV .node polygon,#mermaid-svg-3h1oYNQLLUj7gEkV .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-3h1oYNQLLUj7gEkV .rough-node .label text,#mermaid-svg-3h1oYNQLLUj7gEkV .node .label text,#mermaid-svg-3h1oYNQLLUj7gEkV .image-shape .label,#mermaid-svg-3h1oYNQLLUj7gEkV .icon-shape .label{text-anchor:middle;}#mermaid-svg-3h1oYNQLLUj7gEkV .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-3h1oYNQLLUj7gEkV .rough-node .label,#mermaid-svg-3h1oYNQLLUj7gEkV .node .label,#mermaid-svg-3h1oYNQLLUj7gEkV .image-shape .label,#mermaid-svg-3h1oYNQLLUj7gEkV .icon-shape .label{text-align:center;}#mermaid-svg-3h1oYNQLLUj7gEkV .node.clickable{cursor:pointer;}#mermaid-svg-3h1oYNQLLUj7gEkV .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-3h1oYNQLLUj7gEkV .arrowheadPath{fill:#333333;}#mermaid-svg-3h1oYNQLLUj7gEkV .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-3h1oYNQLLUj7gEkV .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-3h1oYNQLLUj7gEkV .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-3h1oYNQLLUj7gEkV .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-3h1oYNQLLUj7gEkV .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-3h1oYNQLLUj7gEkV .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-3h1oYNQLLUj7gEkV .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-3h1oYNQLLUj7gEkV .cluster text{fill:#333;}#mermaid-svg-3h1oYNQLLUj7gEkV .cluster span{color:#333;}#mermaid-svg-3h1oYNQLLUj7gEkV div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-3h1oYNQLLUj7gEkV .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-3h1oYNQLLUj7gEkV rect.text{fill:none;stroke-width:0;}#mermaid-svg-3h1oYNQLLUj7gEkV .icon-shape,#mermaid-svg-3h1oYNQLLUj7gEkV .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-3h1oYNQLLUj7gEkV .icon-shape p,#mermaid-svg-3h1oYNQLLUj7gEkV .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-3h1oYNQLLUj7gEkV .icon-shape .label rect,#mermaid-svg-3h1oYNQLLUj7gEkV .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-3h1oYNQLLUj7gEkV .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-3h1oYNQLLUj7gEkV .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-3h1oYNQLLUj7gEkV :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} http
静态资源
/chat_py_server/* 反向代理
浏览器
Nginx
chat_py_front 前端
chat_py_server 后端
DeepSeek / 内部 LLM
Milvus 向量库
本地 Embedding 模型 bge-base-zh-v1.5
MySQL: sys_user
Redis: 验证码
SQLite: 会话记忆 / 会话索引
外部业务接口: 企业信息 / 联网搜索
说明:
- 前端为纯静态 SPA,由 Nginx 托管;接口统一走
/chat_py_server/*,由 Nginx 反向代理到后端5020端口,避免跨域。 - 后端为核心,负责鉴权、多智能体编排、工具调用、RAG 检索、报表生成。
- 大模型调用 DeepSeek(主)与内部 LLM。
- 向量检索依赖 Milvus,Embedding 在容器内使用本地模型 CPU 推理。
4.2 后端分层
text
controller(接口层)
↓
graph(主管编排层:supervisor_graph / agent_descriptions)
↓
tools(子智能体工具层)
↓
service(业务服务层:model / system)
↓
entity + config + model(实体 / 配置 / LLM 客户端)
- controller :
chat_controller(对话)、auth_controller(登录)、doc_controller(文档上传)。 - graph:主管智能体迭代编排,主管分析问题 → 选择工具 → 并行调用 → 总结输出。
- tools :每个子智能体是一个
BaseTool,统一注册到主管的可用工具列表。 - service/system:Milvus、Embedding、Redis、DB、鉴权、会话等基础服务。
4.3 核心流程
4.3.1 对话编排流程(LangGraph)
- 前端把
messages、conversationId、skill通过 SSE 请求发送到/chat_py_server/chat/v1/chat/completions。 - 后端鉴权(JWT)后进入
SupervisorGraph。 supervisor节点根据用户问题 + 历史对话 + 已选技能,输出本轮要调用的工具列表(JSON)。tool_caller节点并行调用选中的工具,累计结果。- 若还需跨工具依赖(如先查信用代码再查详情),回到
supervisor继续迭代。 summarize节点综合工具结果,流式生成最终回答;generate_report的结构化结果直接透传(不交给 LLM 改写)。
4.3.2 知识库检索(RAG)
- 文档上传(
doc_controller)→ 读取文本 → 切割 → Embedding → 写入 Milvus 集合。 - 提问时
search_knowledge_base工具将问题向量化 → Milvus 检索 Top-K → 拼成上下文 → 交给大模型生成回答。
4.3.3 登录鉴权流程
GET /captchaImage生成图形验证码并缓存到 Redis。POST /login校验验证码 → 查 MySQLsys_user→ 校验status→ BCrypt 校验密码 → 签发 JWT。GET /getInfo解析 JWT 返回当前用户信息。- 后续请求通过
Authorization: Bearer <token>鉴权。
5. 开发流程
5.1 后端本地开发
powershell
cd e:\myProject\my-langchain\chat_py_server
# 1) 创建并激活虚拟环境(可选)
python -m venv .venv
.\.venv\Scripts\Activate.ps1
# 2) 安装依赖
pip install -r requirements.txt
# 3) 配置 .env(数据库、Redis、Milvus、模型密钥等)
# 4) 启动(监听 5020)
python app.py
注意:
embedding_service在启动时加载本地 Embedding 模型,首次启动较慢;DEVICE=cpu需本机已存在模型路径EMBEDDING_MODEL_PATH。
5.2 前端本地开发
powershell
cd e:\myProject\my-langchain\chat_py_front
npm install
npm run dev
开发环境通过 Vite 代理把
/chat_py_server转发到http://127.0.0.1:5020(见vite.config.js),无需处理跨域。
5.3 新增一个子智能体工具
- 在
app/tools/新建xxx_tool.py,继承langchain_core.tools.BaseTool,定义name、description、args_schema与_run。 - 在
app/tools/__init__.py导出工具类。 - 在
app/graph/agent_descriptions.py注册ToolDescription并加入ALL_TOOLS。 - 在
app/graph/supervisor_graph.py的_TOOL_INSTANCES与_execute_single_tool增加分发逻辑。
5.4 新增一个技能
- 在
app/skills/<skill-name>/SKILL.md编写技能定义(参考company-detail/SKILL.md)。 - 在
app/graph/agent_descriptions.py的SKILL_TOOL_MAP中把技能名映射到目标工具。 - 前端
Chat.vue的skillOptions中加入该技能选项。
6. 注意事项
- 端口与入口 :后端监听
5020,入口文件是app.py(内部调用uvicorn.run)。镜像采用「Dockerfile.base装依赖 +Dockerfile只 COPY 源码」两层构建,CMD为python app.py。 - 容器内监听地址 :
.env中SERVER_HOST若为127.0.0.1,容器内只能本机访问,需改为0.0.0.0。 SERVER_WORKERS=1:LangGraph 使用AsyncSqliteSaver会话记忆,且 Embedding 模型/工具实例在进程内加载,建议保持单 worker,避免多进程资源重复与 SQLite 竞争。- SSE 流式 :对话接口为 SSE 流式输出,Nginx 反向代理需关闭缓冲(
proxy_buffering off)并调大proxy_read_timeout。 - Embedding 模型 :容器内
EMBEDDING_MODEL_PATH需指向挂载进来的模型目录(如/opt/embedding_model),且内存需足够(torch CPU + 模型约需数 GB)。模型目录顶层必须包含config.json与pytorch_model.bin/model.safetensors,否则启动报OSError。 - 前端子路径 :前端部署在
/chat_py_front/子路径时,需设置 Vitebase与 Vue RoutercreateWebHistory('/chat_py_front/'),否则资源引用仍为根路径/assets/...导致 404。 - Nginx 502 :Nginx 反向代理 502 通常是连不到后端
127.0.0.1:5020,常见于 Nginx 跑在容器内(127.0.0.1指向容器自身)或 RedHat SELinux 拦截出站连接,详见 7.6。 - 大模型密钥 :DeepSeek / 内部 LLM / 博查 / 智谱等密钥在
.env中配置,注意保密,不要提交到仓库。 sys_user表 :登录依赖 MySQL 中若依标准的sys_user表(user_id、user_name、nick_name、password、status、del_flag),密码需为 BCrypt 密文。- 报表/会话持久化 :报表文件、
checkpoints.sqlite(会话记忆)、conversations.sqlite(会话索引)默认写在项目根目录,容器部署建议挂载到宿主机目录以免重启丢失。 - Milvus 集合 :文档知识库集合
ai_demo_doc会在上传文档时自动创建;网站页面集合ai_demo_website需按业务预先写入。
7. 部署详细步骤
前提:服务器已安装 Docker / Docker Compose,且 MySQL、Redis 已安装(本方案不再安装它们)。
部署组件清单:
| 组件 | 部署方式 | 端口 |
|---|---|---|
| Milvus(etcd + minio + standalone) | docker-compose-milvus.yml | 19530 / 9091 / 9000 / 9001 |
| chat_py_server(后端) | Docker 构建 | 5020 |
| chat_py_front(前端) | 构建静态产物 + Nginx | 80 |
7.1 部署 Milvus
服务器上使用仓库已有的 docker-compose-milvus.yml(镜像已确认可用):
bash
cd /path/to/chat_py_server
# 启动 Milvus(etcd、minio、milvus-standalone)
docker compose -f docker-compose-milvus.yml up -d
# 查看状态
docker compose -f docker-compose-milvus.yml ps
docker logs -f milvus-standalone
默认暴露:
19530:Milvus gRPC 服务端口(后端通过它连接)9091:Milvus 健康检查9000/9001:MinIO 存储
验证连通:
bash
curl -f http://127.0.0.1:9091/healthz
默认账号为
root/Milvus(与.env一致)。若服务器网络环境不同,请把后端.env中MILVUS_URL指向实际可访问地址。
7.2 准备后端配置(.env)
在 chat_py_server/.env 中调整以下项为部署环境实际值:
dotenv
# 监听地址必须为 0.0.0.0,容器外部才能访问
SERVER_HOST="0.0.0.0"
SERVER_PORT=5020
SERVER_WORKERS=1
# Embedding 模型:指向容器内挂载路径
EMBEDDING_MODEL_PATH="/opt/embedding_model"
# Milvus:本机部署则为 http://<服务器内网IP>:19530
MILVUS_URL="http://<服务器内网IP>:19530"
MILVUS_USER="root"
MILVUS_PASSWORD="Milvus"
# MySQL(已安装,按实际填写)
MYSQL_HOST="<mysql地址>"
MYSQL_PORT=3306
MYSQL_USER="root"
MYSQL_PASSWORD="<密码>"
MYSQL_DATABASE="demo"
# Redis(已安装,按实际填写)
REDIS_HOST="<redis地址>"
REDIS_PORT=6379
REDIS_PASSWORD="<密码>"
REDIS_DB=1
7.3 部署后端 chat_py_server(Docker)
7.3.1 构建文件(基础镜像 + 应用镜像)
为避免每次改代码都重新安装依赖,采用两层镜像:
Dockerfile.base:安装全部依赖,构建为chat_py_server:base(仅requirements.txt变化时重建)。Dockerfile:基于chat_py_server:base,只COPY . .,构建为chat_py_server:latest。.dockerignore:排除.env、数据目录、缓存等,避免密钥打进镜像并加快 COPY。
Dockerfile.base:
dockerfile
FROM python:3.10-slim
LABEL maintainer="jxbd"
WORKDIR /app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt \
-i https://pypi.tuna.tsinghua.edu.cn/simple \
--default-timeout=600
Dockerfile:
dockerfile
FROM chat_py_server:base
LABEL maintainer="jxbd"
WORKDIR /app
COPY . .
CMD ["python", "app.py"]
.dockerignore:
text
.env
__pycache__/
*.pyc
.venv/
venv/
data/
report_files/
checkpoints.sqlite
conversations.sqlite
*.sqlite
.git/
.gitignore
*.md
docs/
docker-compose*.yml
Dockerfile*
说明:
torch==2.6.0默认安装 CPU 版,基础镜像体积较大,但只需在requirements.txt变化时重建一次。
7.3.2 docker-compose.yml
使用以下 chat_py_server/docker-compose.yml(挂载模型、.env、数据目录):
yaml
version: "3.8"
services:
chat_py_server:
image: chat_py_server:latest
container_name: chat_py_server
environment:
SERVER_HOST: "0.0.0.0"
SERVER_PORT: "5020"
EMBEDDING_MODEL_PATH: "/opt/embedding_model"
LANGGRAPH_SQLITE_PATH: "/app/data/checkpoints.sqlite"
CONVERSATION_SQLITE_PATH: "/app/data/conversations.sqlite"
REPORT_FILE_DIR: "/app/data/report_files"
volumes:
- "./.env:/app/.env"
# 宿主机 Embedding 模型目录(按实际路径修改)
- "/opt/chat/bertmodel/BAAI/bge-base-zh-v1.5:/opt/embedding_model"
# 数据持久化
- "./data:/app/data"
ports:
- "5020:5020"
restart: unless-stopped
environment中的变量会覆盖.env中的同名配置(load_dotenv默认不覆盖已存在的环境变量)。MILVUS_URL建议直接在.env中配置。挂载源
/opt/chat/bertmodel/BAAI/bge-base-zh-v1.5必须是包含config.json与pytorch_model.bin/model.safetensors的那一层目录,否则启动报OSError(见 7.6)。
7.3.3 构建并启动
bash
cd /path/to/chat_py_server
mkdir -p data
# 1) 基础镜像:仅 requirements.txt 变化时重建
docker build -f Dockerfile.base -t chat_py_server:base .
# 2) 应用镜像:每次改代码后构建(很快,不再 pip install)
docker build -t chat_py_server:latest .
# 3) 启动
docker compose up -d
# 4) 实时查看日志(Ctrl+C 退出)
docker compose logs -f chat_py_server
验证:
bash
curl http://127.0.0.1:5020/chat_py_server/auth/v1/captchaImage
7.3.4 不使用 docker compose 的等价命令(可选)
bash
cd /path/to/chat_py_server
docker build -f Dockerfile.base -t chat_py_server:base .
docker build -t chat_py_server:latest .
docker run -d \
--name chat_py_server \
-p 5020:5020 \
-e SERVER_HOST=0.0.0.0 \
-e EMBEDDING_MODEL_PATH=/opt/embedding_model \
-v "$(pwd)/.env:/app/.env" \
-v "/opt/chat/bertmodel/BAAI/bge-base-zh-v1.5:/opt/embedding_model" \
-v "$(pwd)/data:/app/data" \
--restart unless-stopped \
chat_py_server:latest
7.4 部署前端 chat_py_front
前端以 /chat_py_front/ 子路径部署(与后端 /chat_py_server/ 区分)。
7.4.1 配置子路径
vite.config.js生产构建base设为/chat_py_front/(开发环境保持/):
js
export default defineConfig(({ mode }) => ({
base: mode === 'production' ? '/chat_py_front/' : '/',
// ...其余配置
}))
src/router/index.js路由 base 设为/chat_py_front/:
js
const router = createRouter({
history: createWebHistory('/chat_py_front/'),
routes,
})
这一步必须做,否则打包后
index.html里的资源仍引用根路径/assets/...,部署到子路径会 404。
7.4.2 构建静态产物
bash
cd /path/to/chat_py_front
npm install
npm run build
构建产物在 chat_py_front/dist/,上传到服务器 /opt/project/front/chat_py_front/。
前端默认
VITE_API_BASE为空,接口走同源/chat_py_server/*,由 Nginx 反向代理,无需修改。
7.4.3 部署到 Nginx
Nginx 配置(注意 root 写父目录 /opt/project/front/,不要重复写 chat_py_front):
nginx
server {
listen 80;
server_name medaide.com.cn;
# 前端静态资源(子路径部署)
location /chat_py_front/ {
root /opt/project/front/;
index index.html;
try_files $uri $uri/ /chat_py_front/index.html;
}
# 后端接口反向代理(含 SSE 流式)
location /chat_py_server/ {
proxy_pass http://127.0.0.1:5020;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# SSE 流式必须关闭缓冲并调大超时
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 300s;
}
}
重载 Nginx:
bash
nginx -t
nginx -s reload
浏览器访问 https://medaide.com.cn/chat_py_front/,使用 MySQL sys_user 中的账号密码登录。
若 Nginx 跑在 Docker 容器里,
proxy_pass http://127.0.0.1:5020连的是容器自身,需改成宿主机内网 IP 或host.docker.internal(见 7.6)。
7.5 部署后联调验证
- 登录验证
bash
# 获取验证码
curl http://<服务器IP>/chat_py_server/auth/v1/captchaImage
# 登录(需先填写正确验证码 uuid/code)
curl -X POST http://<服务器IP>/chat_py_server/auth/v1/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"<密码>","code":"<验证码>","uuid":"<uuid>"}'
# 获取用户信息
curl http://<服务器IP>/chat_py_server/auth/v1/getInfo \
-H "Authorization: Bearer <token>"
-
对话验证:浏览器登录后发起提问,确认 SSE 流式回答正常、图表正常渲染、报表可下载。
-
知识库验证:通过文档上传接口写入文档后,选择"知识库查询"技能提问,确认能检索到文档内容。
7.6 常见问题排查
后端启动报 OSError: no file named pytorch_model.bin/model.safetensors
说明挂载到 /opt/embedding_model 的目录里没有模型权重文件。模型目录顶层必须包含 config.json 与 pytorch_model.bin(或 model.safetensors)。
bash
ls -la /opt/chat/bertmodel/BAAI/bge-base-zh-v1.5
find /opt/chat/bertmodel -name "pytorch_model.bin" -o -name "model.safetensors" 2>/dev/null
把 docker-compose 的挂载源改成真正包含权重文件的那一层目录,再 docker compose up -d 重启。
访问接口 502
502 表示 Nginx 连不上后端 127.0.0.1:5020。先本地验证后端是否正常:
bash
curl http://127.0.0.1:5020/chat_py_server/auth/v1/captchaImage
-
本地 curl 通、Nginx 502 → 大概率是以下之一:
-
Nginx 跑在 Docker 容器里,其
127.0.0.1指向容器自身,需改proxy_pass http://<宿主机内网IP>:5020(或用host.docker.internal)。 -
RedHat/CentOS 的 SELinux 拦截 Nginx 出站连接:
bashsetsebool -P httpd_can_network_connect 1
-
-
本地 curl 不通 → 后端没起来,用
docker compose logs -f chat_py_server看崩溃原因(多为模型路径问题)。
前端资源 404 / 500
- 资源路径仍是
/assets/...(无/chat_py_front/前缀)→ 前端没按 7.4.1 设置base或没重新构建部署,重新npm run build并覆盖dist/。 - Nginx 报
internal redirection cycle→root写重了chat_py_front,root应写父目录/opt/project/front/。 - Nginx 报 403 → 检查文件权限(
chmod -R 755)、SELinux 上下文(chcon -R -t httpd_sys_content_t)。
实时查看后端日志
bash
cd /path/to/chat_py_server
docker compose logs -f chat_py_server
docker compose logs -f --tail=200 chat_py_server
# 或
docker logs -f --tail=200 chat_py_server
8. 附录:关键配置项速查
| 配置项 | 说明 | 默认值 |
|---|---|---|
SERVER_HOST / SERVER_PORT |
后端监听地址与端口 | 127.0.0.1 / 5020 |
SERVER_PREFIX |
接口前缀 | chat_py_server |
DEEPSEEK_API_* |
DeepSeek 模型接入 | --- |
LLM_API_* |
内部大模型接入 | --- |
EMBEDDING_MODEL_PATH |
本地 Embedding 模型路径 | --- |
MILVUS_URL / MILVUS_USER / MILVUS_PASSWORD |
向量库连接 | --- |
MILVUS_COLLECTION_DOC |
文档知识库集合 | ai_demo_doc |
MILVUS_COLLECTION_WEBSITE |
网站页面集合 | ai_demo_website |
MYSQL_* |
登录鉴权数据库 | --- |
REDIS_* |
验证码缓存 | --- |
JWT_SECRET / JWT_EXPIRE_MINUTES |
JWT 密钥与有效期 | --- |
CAPTCHA_ENABLED / CAPTCHA_EXPIRE_MINUTES |
验证码开关与有效期 | true / 2 |
REPORT_FILE_DIR |
报表文件目录 | report_files |
LANGGRAPH_SQLITE_PATH |
会话记忆 SQLite | checkpoints.sqlite |
CONVERSATION_SQLITE_PATH |
会话索引 SQLite | conversations.sqlite |