上一篇 下一篇 分享链接 返回 返回顶部

1. 企业内网也能用的“ChatGPT”:从部署到源码一次讲清 2. 手把手搭一套企业私有 AI 助手:架构、RAG 与源码实战 3. 不把数据交出去:企业级 ChatGPT 私有化部署完整方案 4. 从 0 到 1 搭建私有化 ChatGPT:模型、知识库、权限与源码 5. 企业私有 AI 助手落地指南:可部署、可接入、可管控 6. 内网版 ChatGPT 怎么做?一套可运行的私有化部署方案 7. 把大模型装进企业内网:私有化 ChatGPT 实战方案 8. 企业知识库问答系

发布人:慈云数据-客服中心 发布时间:14小时前 阅读量:6

ChatGPT 私有化部署方案|附源码

说明:严格来说,OpenAI 官方 ChatGPT 本体并不支持私有化部署。我们日常所说的“ChatGPT 私有化部署”,通常指的是在企业内网或私有云中部署一套类似 ChatGPT 的智能问答系统,包括:大语言模型、对话服务、知识库检索、权限控制、审计日志、前端聊天界面等能力。

本文将从架构设计、模型选型、部署方案、接口服务、前端页面、知识库增强以及安全治理等方面,完整介绍一套可落地的 ChatGPT 私有化部署方案,并附上可运行的核心源码示例。


一、为什么需要 ChatGPT 私有化部署?

随着大语言模型在企业办公、研发、客服、知识管理、数据分析等场景中的广泛应用,越来越多的企业开始关注私有化部署方案。相比直接使用公有云 AI 服务,私有化部署主要有以下优势:

1. 数据安全可控

企业内部文档、合同、代码、客户资料、财务数据往往具有较高敏感性。如果直接上传到第三方平台,可能存在数据泄露、合规审计困难等问题。

私有化部署后,数据可以保留在企业内网或专属私有云环境中,访问链路、日志存储、权限控制都由企业自主掌握。

2. 满足合规要求

金融、政务、医疗、能源、军工等行业对数据合规要求较高,很多场景不允许业务数据流出专有网络。私有化部署可以更好地满足等保、数据安全法、个人信息保护法以及行业监管要求。

3. 成本可控

如果企业内部有大量员工频繁使用 AI 能力,长期按量调用公有云模型接口,成本可能较高。通过本地部署开源大模型,可以在硬件投入之后,将单位调用成本控制在更低水平。

4. 支持深度定制

私有化部署不仅可以替换模型,还可以结合企业知识库、业务系统、内部 API、权限体系、审计系统进行深度集成。例如:

  • 企业内部智能客服;
  • 研发代码助手;
  • 合同审核助手;
  • 运维问答机器人;
  • 内部制度查询助手;
  • 数据报表分析助手;
  • OA、CRM、ERP 智能助手。

二、整体架构设计

一套较完整的 ChatGPT 私有化部署系统,通常由以下几部分组成:

用户浏览器
   │
   ▼
前端聊天界面 Web UI
   │
   ▼
后端 API 服务
   │
   ├── 用户认证与权限控制
   ├── 会话管理
   ├── Prompt 编排
   ├── 模型调用网关
   ├── 知识库检索 RAG
   ├── 敏感词与安全审计
   └── 日志与监控
   │
   ▼
大语言模型推理服务
   │
   ├── Qwen
   ├── DeepSeek
   ├── Llama
   ├── Baichuan
   └── ChatGLM
   │
   ▼
向量数据库 / 文档库 / 业务系统

推荐技术选型

模块 推荐方案
前端 Vue、React、Next.js
后端 FastAPI、Spring Boot、Node.js
模型服务 vLLM、Ollama、Text Generation WebUI、LMDeploy
模型协议 OpenAI-Compatible API
向量数据库 Milvus、Qdrant、Chroma、pgvector
文档解析 unstructured、pdfplumber、python-docx
权限认证 JWT、OAuth2、LDAP、企业微信、飞书
部署方式 Docker Compose、Kubernetes
监控 Prometheus、Grafana、ELK
网关 Nginx、Kong、Traefik

三、模型选型建议

私有化部署的核心是大语言模型。当前可选的开源或开放权重模型较多,常见选择如下:

1. Qwen 系列

通义千问 Qwen 系列中文能力较强,生态完善,适合中文企业知识问答、办公助手、代码辅助等场景。

适合场景:

  • 中文问答;
  • 企业知识库;
  • 办公助手;
  • 多语言任务;
  • 代码生成。

2. DeepSeek 系列

DeepSeek 在代码、数学、推理方面表现较好,适合研发团队、数据分析、逻辑推理类应用。

适合场景:

  • 代码助手;
  • SQL 生成;
  • 数学推理;
  • 技术文档问答;
  • 智能研发平台。

3. Llama 系列

Llama 生态成熟,英文能力强,社区资源丰富。如果企业有较多英文资料或海外业务,可以考虑使用。

4. ChatGLM 系列

ChatGLM 中文对话能力较好,部署资料较多,对国内用户比较友好。

5. 模型规模选择

模型规模 显存需求 适用场景
7B / 8B 8GB - 16GB 轻量问答、测试、个人助手
14B 24GB - 48GB 中小企业知识库、办公助手
32B 64GB - 80GB 复杂问答、代码、推理
70B+ 160GB+ 高质量生成、复杂推理、大规模企业应用

如果是企业正式使用,建议至少选择 14B 以上模型。如果预算有限,可以先使用 7B/8B 版本做验证,再根据效果逐步升级。


四、部署方式选择

方案一:Ollama 快速部署

Ollama 适合快速体验和中小规模使用,安装简单,命令清晰,非常适合内部 Demo 或轻量级私有助手。

安装 Ollama

Linux 环境下执行:

curl -fsSL https://ollama.com/install.sh | sh

拉取模型

以 Qwen 为例:

ollama pull qwen2.5:7b

启动模型服务

ollama serve

默认服务地址:

http://localhost:11434

测试调用

curl http://localhost:11434/api/chat -d '{
  "model": "qwen2.5:7b",
  "messages": [
    {
      "role": "user",
      "content": "请介绍一下私有化部署大模型的优势"
    }
  ]
}'

方案二:vLLM 高性能部署

如果企业用户较多,需要支持并发访问,推荐使用 vLLM。vLLM 支持连续批处理、PagedAttention、OpenAI API 兼容接口,适合生产环境。

安装 vLLM

pip install vllm

启动 OpenAI 兼容服务

python -m vllm.entrypoints.openai.api_server \
  --model Qwen/Qwen2.5-14B-Instruct \
  --host 0.0.0.0 \
  --port 8000 \
  --served-model-name private-chatgpt

启动后,服务接口与 OpenAI Chat Completions 接口基本兼容。

测试接口

curl http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer EMPTY" \
  -d '{
    "model": "private-chatgpt",
    "messages": [
      {
        "role": "user",
        "content": "请用三句话解释 RAG 是什么"
      }
    ],
    "temperature": 0.7
  }'

五、Docker Compose 一键部署方案

下面给出一个简化版的私有化 ChatGPT 部署方案,包括:

  • 前端 Web UI;
  • 后端 FastAPI 服务;
  • Ollama 模型服务;
  • Chroma 向量数据库;
  • Nginx 反向代理。

项目目录结构

private-chatgpt/
├── docker-compose.yml
├── nginx/
│   └── default.conf
├── backend/
│   ├── Dockerfile
│   ├── main.py
│   ├── rag.py
│   ├── requirements.txt
│   └── config.py
└── frontend/
    ├── Dockerfile
    ├── package.json
    └── src/
        └── App.vue

六、核心源码

1. docker-compose.yml

version: "3.9"

services:
  ollama:
    image: ollama/ollama:latest
    container_name: private-ollama
    ports:
      - "11434:11434"
    volumes:
      - ./data/ollama:/root/.ollama
    restart: always

  chroma:
    image: chromadb/chroma:latest
    container_name: private-chroma
    ports:
      - "8001:8000"
    volumes:
      - ./data/chroma:/chroma/chroma
    restart: always

  backend:
    build:
      context: ./backend
    container_name: private-chatgpt-backend
    ports:
      - "9000:9000"
    environment:
      - OLLAMA_BASE_URL=http://ollama:11434
      - OLLAMA_MODEL=qwen2.5:7b
      - CHROMA_HOST=chroma
      - CHROMA_PORT=8000
    depends_on:
      - ollama
      - chroma
    restart: always

  frontend:
    build:
      context: ./frontend
    container_name: private-chatgpt-frontend
    ports:
      - "8080:80"
    depends_on:
      - backend
    restart: always

2. backend/requirements.txt

fastapi==0.115.0
uvicorn==0.30.6
requests==2.32.3
pydantic==2.8.2
chromadb==0.5.5
sentence-transformers==3.0.1
python-multipart==0.0.9

3. backend/config.py

import os

OLLAMA_BASE_URL = os.getenv("OLLAMA_BASE_URL", "http://localhost:11434")
OLLAMA_MODEL = os.getenv("OLLAMA_MODEL", "qwen2.5:7b")

CHROMA_HOST = os.getenv("CHROMA_HOST", "localhost")
CHROMA_PORT = int(os.getenv("CHROMA_PORT", "8000"))

SYSTEM_PROMPT = """
你是企业内部私有化部署的智能助手。
你需要遵守以下规则:
1. 回答必须准确、清晰、专业;
2. 如果知识库中没有相关信息,请明确说明不知道;
3. 不要编造企业制度、合同条款或业务数据;
4. 对敏感数据保持谨慎,不输出未授权信息;
5. 优先使用用户提供的上下文和企业知识库内容。
"""

4. backend/main.py

from fastapi import FastAPI, UploadFile, File
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
import requests

from config import OLLAMA_BASE_URL, OLLAMA_MODEL, SYSTEM_PROMPT
from rag import add_document, search_documents

app = FastAPI(title="Private ChatGPT API")

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

class ChatRequest(BaseModel):
    message: str
    use_rag: bool = True

class ChatResponse(BaseModel):
    answer: str

@app.get("/health")
def health():
    return {"status": "ok"}

@app.post("/chat", response_model=ChatResponse)
def chat(req: ChatRequest):
    context = ""

    if req.use_rag:
        docs = search_documents(req.message, top_k=3)
        if docs:
            context = "\n\n".join(docs)

    prompt = f"""
{SYSTEM_PROMPT}

以下是企业知识库中检索到的相关内容:
{context if context else "未检索到相关知识库内容。"}

用户问题:
{req.message}

请基于以上信息进行回答。
"""

    payload = {
        "model": OLLAMA_MODEL,
        "messages": [
            {
                "role": "system",
                "content": SYSTEM_PROMPT
            },
            {
                "role": "user",
                "content": prompt
            }
        ],
        "stream": False
    }

    resp = requests.post(
        f"{OLLAMA_BASE_URL}/api/chat",
        json=payload,
        timeout=120
    )

    resp.raise_for_status()
    data = resp.json()

    return ChatResponse(answer=data["message"]["content"])

@app.post("/upload")
async def upload(file: UploadFile = File(...)):
    content = await file.read()

    try:
        text = content.decode("utf-8")
    except UnicodeDecodeError:
        return {
            "success": False,
            "message": "当前示例仅支持 UTF-8 文本文档,请扩展 PDF、Word 解析能力。"
        }

    add_document(file.filename, text)

    return {
        "success": True,
        "filename": file.filename,
        "message": "文档已写入知识库"
    }

5. backend/rag.py

import chromadb
from chromadb.config import Settings
from sentence_transformers import SentenceTransformer
from config import CHROMA_HOST, CHROMA_PORT

client = chromadb.HttpClient(
    host=CHROMA_HOST,
    port=CHROMA_PORT,
    settings=Settings(allow_reset=False)
)

collection = client.get_or_create_collection(name="enterprise_docs")

embedding_model = SentenceTransformer("sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2")

def split_text(text: str, chunk_size: int = 500, overlap: int = 80):
    chunks = []
    start = 0

    while start < len(text):
        end = start + chunk_size
        chunk = text[start:end]
        chunks.append(chunk)
        start = end - overlap

    return chunks

def embed(texts):
    return embedding_model.encode(texts).tolist()

def add_document(filename: str, text: str):
    chunks = split_text(text)

    ids = []
    metadatas = []

    for index, chunk in enumerate(chunks):
        ids.append(f"{filename}-{index}")
        metadatas.append({
            "filename": filename,
            "chunk_index": index
        })

    vectors = embed(chunks)

    collection.add(
        ids=ids,
        documents=chunks,
        embeddings=vectors,
        metadatas=metadatas
    )

def search_documents(query: str, top_k: int = 3):
    query_vector = embed([query])[0]

    result = collection.query(
        query_embeddings=[query_vector],
        n_results=top_k
    )

    documents = result.get("documents", [[]])[0]

    return documents

6. backend/Dockerfile

FROM python:3.11-slim

WORKDIR /app

COPY requirements.txt .

RUN pip install --no-cache-dir -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple

COPY . .

EXPOSE 9000

CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "9000"]

7. frontend/src/App.vue