运维团队做内部AI问答,常见的选型困惑是:Dify还是FastGPT?
简单回答:如果核心需求是知识库问答,FastGPT是更直接的选择。它的部署更简单,知识库相关的功能更细(切片预览、召回测试都很直观),对话效果开箱即用就不错。
如果需要复杂工作流编排(条件分支、多步骤处理、外部API调用),Dify更合适。
这篇文章覆盖FastGPT的完整使用流程,从部署到运维知识库实战。
FastGPT vs Dify:选型参考#
| 维度 | FastGPT | Dify |
|---|---|---|
| 部署复杂度 | 较低 | 中等 |
| 知识库功能 | 丰富,专注 | 够用 |
| 工作流 | 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自动生成问答对,而不是直接切片存储原文。
工作原理:
- 把文档分段
- AI为每段生成多个问题
- 每个问题关联对应的原文段落
- 检索时用问题匹配用户输入,命中率更高
代价:消耗更多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效果会比自由格式好很多。
定期维护#
知识库不是一劳永逸的,需要定期维护:
- 月度Review:抽取最近一个月的问答记录,找出"无法回答"或"答错"的问题,补充对应文档
- 故障后总结:每次故障处理后,把故障原因、排查过程、解决方法加入故障案例库
- 文档同步:运维文档更新后,在知识库里同步更新对应切片
常见问题#
Q:为什么同样的问题,有时有答案有时说"没找到相关信息"?
向量检索有一定的随机性,相同问题的不同表达方式可能导致相似度不同。解决:
- 降低最低相似度阈值
- 用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) }
})






