跳过正文
FastGPT 知识库问答系统:从部署到应用

FastGPT 知识库问答系统:从部署到应用

·733 字·4 分钟·
目录
AI 工程化实战 - 这篇文章属于一个选集。
§ : 本文

运维团队做内部AI问答,常见的选型困惑是:Dify还是FastGPT?

简单回答:如果核心需求是知识库问答,FastGPT是更直接的选择。它的部署更简单,知识库相关的功能更细(切片预览、召回测试都很直观),对话效果开箱即用就不错。

如果需要复杂工作流编排(条件分支、多步骤处理、外部API调用),Dify更合适。

这篇文章覆盖FastGPT的完整使用流程,从部署到运维知识库实战。


FastGPT vs Dify:选型参考
#

维度FastGPTDify
部署复杂度较低中等
知识库功能丰富,专注够用
工作流Flow(偏对话流程)工作流(偏数据处理流程)
Agent能力基础更完整
多应用类型偏聊天聊天/文本生成/Agent
社区活跃度活跃非常活跃
适合场景知识库问答、FAQ机器人复杂LLM应用、工作流自动化

Docker部署
#

FastGPT依赖MongoDB(存储应用数据)和PgVector(向量存储),Docker Compose可以一次性启动所有服务。

配置文件准备
#

mkdir fastgpt && cd fastgpt

创建docker-compose.yml

version: '3.3'
services:
  # MongoDB
  mongo:
    image: mongo:5.0.18
    container_name: fastgpt-mongo
    ports:
      - "27017:27017"
    environment:
      MONGO_INITDB_ROOT_USERNAME: myusername
      MONGO_INITDB_ROOT_PASSWORD: mypassword
    volumes:
      - ./mongo/data:/data/db
    restart: unless-stopped
    command: mongod --quiet

  # PostgreSQL with PgVector
  pg:
    image: ankane/pgvector:v0.5.0
    container_name: fastgpt-pg
    ports:
      - "5432:5432"
    environment:
      POSTGRES_USER: username
      POSTGRES_PASSWORD: password
      POSTGRES_DB: postgres
    volumes:
      - ./pg/data:/var/lib/postgresql/data
    restart: unless-stopped

  # FastGPT
  fastgpt:
    image: ghcr.io/labring/fastgpt:latest
    container_name: fastgpt
    ports:
      - "3000:3000"
    depends_on:
      - mongo
      - pg
    environment:
      # MongoDB连接
      MONGODB_URI: mongodb://myusername:mypassword@mongo:27017/fastgpt?authSource=admin
      # PgVector连接
      PG_URL: postgresql://username:password@pg:5432/postgres
      # 向量模型(这里用OpenAI,也可以换成本地)
      VECTOR_MAX_PROCESS_LEN: 512
      OPENAI_BASE_URL: https://api.openai.com/v1
      # 初始化Root账号密码
      DEFAULT_ROOT_PSW: your-admin-password
      # 加密密钥
      TOKEN_KEY: your-random-token-key
      ROOT_KEY: your-random-root-key
      FILE_TOKEN_KEY: your-file-token-key
    volumes:
      - ./config.json:/app/data/config.json
    restart: unless-stopped

config.json配置
#

FastGPT的核心配置在config.json,控制可用的模型和向量模型:

{
  "feConfigs": {
    "lafEnv": "https://laf.dev",
    "show_emptyChat": true,
    "show_contact": false,
    "show_git": true,
    "show_register": false,
    "show_appStore": false,
    "isPlus": false,
    "show_openai_account": true
  },
  "systemEnv": {
    "openapiPrefix": "fastgpt",
    "vectorMaxProcess": 15,
    "qaMaxProcess": 15,
    "pgHNSWEfSearch": 100
  },
  "llmModels": [
    {
      "model": "gpt-4o",
      "name": "GPT-4o",
      "avatar": "/imgs/model/openai.svg",
      "maxContext": 128000,
      "maxResponse": 16000,
      "quoteMaxToken": 100000,
      "maxTemperature": 1.2,
      "vision": true,
      "toolChoice": true,
      "functionCall": false,
      "defaultSystemChatPrompt": ""
    },
    {
      "model": "gpt-4o-mini",
      "name": "GPT-4o-mini",
      "avatar": "/imgs/model/openai.svg",
      "maxContext": 128000,
      "maxResponse": 16000,
      "quoteMaxToken": 100000,
      "maxTemperature": 1.2,
      "vision": true,
      "toolChoice": true,
      "functionCall": false,
      "defaultSystemChatPrompt": ""
    }
  ],
  "vectorModels": [
    {
      "model": "text-embedding-3-small",
      "name": "Embedding-3-small",
      "avatar": "/imgs/model/openai.svg",
      "charsPointsPrice": 0,
      "defaultToken": 512,
      "maxToken": 3000,
      "weight": 100
    }
  ],
  "audioSpeechModels": [],
  "whisperModel": {},
  "reRankModels": []
}

启动和验证
#

docker compose up -d

# 查看启动日志
docker compose logs fastgpt -f

# 看到 "Server started" 说明启动完成
# 访问 http://your-server:3000

默认账号:

  • 用户名:root
  • 密码:你在DEFAULT_ROOT_PSW里设置的值

配置API Key
#

登录后,右上角用户名 → 账号 → API密钥 里配置OpenAI API Key。

FastGPT使用中转模型,所有用户的API请求都走这里配置的Key(而不是每个用户单独配置)。


知识库创建与文档导入
#

创建知识库
#

左侧菜单 → 知识库 → 新建知识库

填写名称,选择向量模型(决定了文档怎么被向量化,创建后不能修改)。

文档导入
#

支持多种导入方式:

手动输入:适合FAQ这种结构化内容,直接填写问题和答案对,效果最好(因为可以精确控制每个切片的内容)。

文件导入:PDF、Word、Markdown、CSV等,自动切分。

CSV批量导入:格式为"问题,答案",适合把现有的FAQ系统迁移过来。

网站抓取:输入URL,FastGPT会爬取并导入(需要在config.json里启用相关功能)。

切片配置
#

上传文件时,“高级"选项里可以调整切片参数:

切片大小(Chunk Size):建议值:

  • 通用文档:400-600字符
  • 技术手册(步骤类):600-1000字符
  • 对话记录/日志:200-400字符

切片重叠(Chunk Overlap):建议10-20%的切片大小,避免关键信息被截断在切片边界。

分隔符:默认按段落分割,也可以自定义分隔符(适合有特殊格式的文档)。

查看切片效果
#

上传完成后,在知识库里可以看到所有切片。点击任意一条可以看到完整内容。

判断切片质量的标准:

  • 每个切片是语义上完整的内容(不是截断一半的句子)
  • 一个切片包含足够的上下文(单独看这段文字能理解含义)
  • 切片里没有大量无意义内容(目录、页眉、页脚)

使用"训练模式"提升效果
#

FastGPT有一个特别的功能:QA拆分。上传文档后,选择用AI自动生成问答对,而不是直接切片存储原文。

工作原理:

  1. 把文档分段
  2. AI为每段生成多个问题
  3. 每个问题关联对应的原文段落
  4. 检索时用问题匹配用户输入,命中率更高

代价:消耗更多token(生成问答对需要调用LLM)。对于内容固定、检索准确率要求高的知识库,值得花这个成本。


Flow工作流配置
#

FastGPT的Flow是针对对话场景设计的工作流,比Dify的工作流更直观。

创建Flow
#

左侧 → 应用 → 新建应用 → 选择"高级编排”

进入Flow编辑器,默认包含"用户问题"和"AI回复"两个节点。

常用节点
#

知识库搜索:连接你的知识库,把召回的内容传给LLM

AI对话:核心节点,配置系统提示词、选择模型

问题分类:让AI判断用户问题属于哪类,然后走不同分支

指定回复:直接输出固定文本(不调用LLM),用于固定问候语等

用户选择:给用户展示选项按钮,用于引导式对话

HTTP请求:调用外部API(需要Plus版本)

典型Flow设计:运维问答机器人
#

用户问题
  ↓
问题分类
  ├─ 告警处理类 → 知识库搜索(告警手册库)→ AI对话 → AI回复
  ├─ 操作指南类 → 知识库搜索(操作手册库)→ AI对话 → AI回复
  └─ 其他        → AI对话(通用模式)→ AI回复

问题分类节点配置

分类标准(提示词里写清楚):

根据用户问题的内容,判断属于哪个类别:
- 告警处理:问题包含告警名称、错误信息、系统报错
- 操作指南:询问如何操作、配置、部署某个系统
- 其他:不属于以上两类的问题

AI对话节点系统提示词
#

你是一个运维技术助手,服务于公司内部运维团队。

【回答原则】
1. 优先使用知识库中的信息,对知识库内容高度信任
2. 如果知识库中没有找到相关信息,明确告知用户
3. 回答要具体可操作,给出完整的命令或步骤
4. 对高风险操作(删除数据、重启服务)要特别提醒

【回答格式】
- 步骤类问题:使用有序列表
- 命令类内容:使用代码块
- 注意事项:使用加粗或引用格式

【知识库引用】
检索到的参考资料:{{quote}}

其中{{quote}}是知识库搜索节点输出的占位符。


问答效果调优
#

相似度阈值调整
#

在知识库搜索节点里,有两个关键参数:

最低相似度(Min Score)

  • 默认:0.5
  • 太高(>0.8):严格但可能漏掉相关内容,出现"找不到相关信息"
  • 太低(<0.4):召回太多不相关内容,LLM被干扰

调优方法:准备20-30个测试问题,逐渐调整阈值,找到召回率和准确率的平衡点。

最多引用Token数(Max Tokens)

  • 控制传给LLM的知识库内容总量
  • 太少:信息不足,答案不完整
  • 太多:超出LLM上下文限制,或增加成本
  • 建议:3000-6000 token,根据使用的模型上下文大小调整

引用数量(Top K)

  • 返回最相关的K个切片
  • 建议:3-8,运维问答用5-6一般效果不错

召回测试
#

这是FastGPT最有用的调优工具。在知识库页面 → “搜索测试” tab:

输入一个问题,查看系统实际召回了哪些切片,以及每个切片的相似度分数。

通过召回测试可以诊断:

  • 用户问了A,但系统召回了B(说明切片内容和用户表达方式不匹配)
  • 相似度分数都很低(说明知识库里没有相关内容,或切片质量问题)
  • 召回了正确内容但答案还是错(说明提示词问题)

提升召回命中率的技巧
#

同义词扩充:在FAQ手动录入时,一个问题录入多种问法:

问题1(主):K8s Pod无法启动怎么办
问题2(别名):Pod CrashLoopBackOff如何处理
问题3(别名):容器一直重启是什么原因
答案:[统一的答案]

关键词增强:在文档切片里,开头加上关键词标注:

[关键词:K8s, Pod, OOMKill, 内存不足]
当Pod因为内存不足被kill时,会出现OOMKilled状态...

文档质量优化

  • 去掉切片里大量重复的模板内容(如每页的页眉版权信息)
  • 表格数据转换为文本描述(表格向量化效果差)
  • 代码块前后加上功能说明(纯代码切片难以被检索)

API接入钉钉/企业微信
#

获取FastGPT API
#

应用详情页 → “API接入” → 复制API Key和接口地址。

FastGPT的API兼容OpenAI格式:

curl -X POST 'https://your-fastgpt-domain/api/v1/chat/completions' \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer app-your-api-key" \
  -d '{
    "chatId": "unique-session-id",
    "stream": false,
    "messages": [{"role": "user", "content": "Pod一直OOMKill怎么办?"}]
  }'

接入钉钉机器人
#

使用钉钉的"企业内部机器人"功能,通过HTTP回调接收消息:

from fastapi import FastAPI, Request
import httpx
import json

app = FastAPI()

FASTGPT_URL = "https://your-fastgpt-domain/api/v1/chat/completions"
FASTGPT_KEY = "app-your-api-key-here"
DINGTALK_TOKEN = "your-dingtalk-outgoing-token"

@app.post("/webhook/dingtalk")
async def dingtalk_webhook(request: Request):
    body = await request.json()
    
    # 验证token
    if body.get("token") != DINGTALK_TOKEN:
        return {"errcode": 403, "errmsg": "Forbidden"}
    
    user_question = body.get("text", {}).get("content", "").strip()
    sender_id = body.get("senderId", "unknown")
    
    # 调用FastGPT
    async with httpx.AsyncClient(timeout=60) as client:
        response = await client.post(
            FASTGPT_URL,
            headers={"Authorization": f"Bearer {FASTGPT_KEY}"},
            json={
                "chatId": f"dingtalk-{sender_id}",
                "stream": False,
                "messages": [{"role": "user", "content": user_question}]
            }
        )
    
    result = response.json()
    answer = result["choices"][0]["message"]["content"]
    
    # 返回给钉钉
    return {
        "msgtype": "markdown",
        "markdown": {
            "title": "运维助手",
            "text": f"**你的问题**:{user_question}\n\n{answer}"
        }
    }

处理会话连续性
#

FastGPT通过chatId维持多轮对话上下文。对于群聊场景,使用群ID+用户ID作为chatId,保持每个人的独立对话历史;对于单聊,使用用户ID即可。


运维知识库实战案例
#

知识库内容规划
#

运维团队的知识库通常包含以下类别,建议分库管理(不同知识库做不同Topic,避免互相干扰):

知识库内容更新频率
告警手册每条告警的含义、处置方法按需更新
操作手册系统操作步骤(部署、回滚、扩容)按版本更新
故障案例历史故障的原因和解决方法故障后总结
架构文档系统架构、依赖关系架构变更后更新
配置规范各系统的配置最佳实践按需更新

告警手册知识库
#

告警手册是运维知识库里ROI最高的部分。格式建议:

# AlertName: KubePodCrashLooping

## 含义
某个Pod在过去一段时间内多次重启,触发了CrashLoopBackOff状态。

## 可能原因
1. 应用启动失败(配置错误、依赖服务不可达)
2. OOMKill(内存不足)
3. 代码bug(panic、未处理的异常)
4. 健康检查配置过于严格

## 排查步骤
1. 查看Pod状态和重启次数:
   `kubectl get pod <pod-name> -n <namespace>`

2. 查看最近的崩溃日志:
   `kubectl logs <pod-name> -n <namespace> --previous`

3. 查看Pod详情(关注Events部分):
   `kubectl describe pod <pod-name> -n <namespace>`

4. 如果是OOMKill,查看内存使用:
   `kubectl top pod <pod-name> -n <namespace>`

## 处理方法
- 配置错误:修复ConfigMap或环境变量,重新部署
- OOMKill:调高memory limits,或排查内存泄漏
- 代码bug:联系开发修复,临时回滚版本

## 升级条件
- 影响生产流量的核心服务 → 立即通知on-call
- 非核心服务重启>10次 → 创建P3工单

这种结构化的格式,FastGPT的RAG效果会比自由格式好很多。

定期维护
#

知识库不是一劳永逸的,需要定期维护:

  1. 月度Review:抽取最近一个月的问答记录,找出"无法回答"或"答错"的问题,补充对应文档
  2. 故障后总结:每次故障处理后,把故障原因、排查过程、解决方法加入故障案例库
  3. 文档同步:运维文档更新后,在知识库里同步更新对应切片

常见问题
#

Q:为什么同样的问题,有时有答案有时说"没找到相关信息"?

向量检索有一定的随机性,相同问题的不同表达方式可能导致相似度不同。解决:

  1. 降低最低相似度阈值
  2. 用QA模式替代直接切片

Q:知识库回答的内容和原文有出入,是LLM在编造吗?

可能是LLM对原文进行了总结/改写,不一定是编造。在系统提示词里明确要求"严格基于参考资料回答,不要改写原文",并在回答里附上原文引用。

Q:MongoDB磁盘用量增长很快怎么办?

MongoDB存储了所有对话历史和索引数据。可以设置对话历史保留时间(在config.json里),定期清理旧数据:

// MongoDB中执行,清理30天前的对话记录
db.chatItems.deleteMany({
  updateTime: { $lt: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000) }
})
Wenzhuo Huang
作者
Wenzhuo Huang
搞运维的工程师,写代码的运维人。专注 Kubernetes、AWS、GitOps 与基础设施可靠性。这个博客既是我的技术笔记本,也是我踩过的坑的受害者档案。
AI 工程化实战 - 这篇文章属于一个选集。
§ : 本文

相关文章

Dify 私有化部署与 RAG 应用构建实战

·665 字·4 分钟
Dify是当前私有化部署最成熟的LLM应用构建平台。本文覆盖Docker Compose部署、多模型Provider配置、知识库创建与切片调优、RAG对话应用构建、工作流编排,以及API发布与生产监控。

LangChain 从入门到实战:构建 LLM 应用的工程框架

·1045 字·5 分钟
LangChain 是构建 LLM 应用最流行的框架,但也是踩坑最多的框架之一。本文从 LCEL 表达式、ReAct Agent、LangGraph 工作流到生产部署,梳理真正有用的部分,并指出哪些功能实际工程中应该避免。