实战:企业内部知识助理——从需求到上线全流程
第21章:实战——企业内部知识助理从需求到上线全流程
本章用一个真实的 800 人制造业企业案例,带你走完需求调研、架构设计、知识库构建、RAG 调优、集成部署的完整旅程。
本章导读
"企业内部知识助理"是 Dify 最典型的落地场景之一。但绝大多数团队在实施时都犯了同样的错误:把所有文档扔进知识库,调一下参数,上线,然后发现用户对答案很不满意。
真正成功的企业知识助理需要经历:需求深挖 → 文档治理 → 知识库分层设计 → RAG 参数调优 → 集成开发 → 用户验收 → 持续迭代六个阶段。
案例背景:某精密制造业企业(800人),拥有以下知识资产:
- HR 文档:员工手册、考勤制度、福利政策(约 500 页 PDF)
- 技术文档:产品规格书、工艺流程手册(约 3000 页,部分有图纸)
- 法规文档:ISO 9001/14001 认证文件、客户审核问卷
- IT 文档:内部系统使用手册(约 200 页)
目标:上线 3 个月内,员工通过 AI 助理自助解决问题的比例从 20% 提升到 65%,HR 和 IT 的重复咨询工单减少 40%。
Level 1:基础认知(1-3 年经验)
需求调研:找到真正的痛点
在动手之前,先花 2 周时间做需求调研。以下是标准化的调研框架:
调研方法一:影子工作法
跟随 HR 专员和 IT 工程师工作 2 天,记录:
- 每天接到的咨询问题类型
- 每次回答花费的时间
- 哪些问题有标准答案(适合 AI 回答)
- 哪些问题需要判断(AI 辅助人工回答)
调研结果(该企业实际数据):
| 咨询类型 | 日均次数 | 平均处理时间 | AI 可解决比例 |
|---|---|---|---|
| 请假流程咨询 | 23 次 | 5 分钟 | 95% |
| 报销规则咨询 | 18 次 | 8 分钟 | 90% |
| 社保公积金问题 | 12 次 | 15 分钟 | 70% |
| 系统操作问题 | 31 次 | 12 分钟 | 80% |
| 产品技术参数查询 | 15 次 | 20 分钟 | 85% |
| 供应商认证要求 | 8 次 | 30 分钟 | 60% |
调研方法二:问题清单收集
在企业 IM 中发起投票,收集"你最希望 AI 帮你回答的工作问题",归类后确定优先级。
文档治理:垃圾进,垃圾出
知识库质量直接决定 AI 回答质量。常见问题:
问题1:文档版本混乱
企业内部往往有多个版本的同一文档(2019年版、2021年版、最新版),混在一起会导致 AI 给出过时信息。
解决方案:建立文档版本控制规范
命名规范:[文档类型]_[版本号]_[生效日期].pdf
示例:员工手册_v3.2_20240101.pdf
上传规则:
- 新版本上传后,同类旧版本必须下线
- 在 Dify 知识库中为每个文档添加元数据:version, effective_date, department
问题2:PDF 扫描版无法提取文字
制造业企业常有大量扫描版 PDF(旧工艺手册、合同扫描件),Dify 默认的 PDF 解析器无法处理。
解决方案:预处理管道
#!/usr/bin/env python3
# pdf_preprocess.py — 扫描 PDF OCR 预处理脚本
import pytesseract
from pdf2image import convert_from_path
from pathlib import Path
def ocr_pdf(input_path: str, output_path: str, lang: str = 'chi_sim+eng') -> str:
"""将扫描 PDF 转换为可检索文本"""
# 转换为图片
images = convert_from_path(input_path, dpi=300)
text_pages = []
for i, image in enumerate(images):
# OCR 识别(支持中英文混合)
text = pytesseract.image_to_string(image, lang=lang)
text_pages.append(f"=== 第 {i+1} 页 ===\n{text}")
full_text = '\n\n'.join(text_pages)
# 保存为 txt 文件(供 Dify 上传)
with open(output_path, 'w', encoding='utf-8') as f:
f.write(full_text)
return full_text
def batch_process(input_dir: str, output_dir: str):
"""批量处理目录中的所有 PDF"""
input_path = Path(input_dir)
output_path = Path(output_dir)
output_path.mkdir(exist_ok=True)
pdfs = list(input_path.glob('**/*.pdf'))
print(f"找到 {len(pdfs)} 个 PDF 文件")
for pdf in pdfs:
out_file = output_path / pdf.with_suffix('.txt').name
if not out_file.exists():
print(f"处理: {pdf.name}")
ocr_pdf(str(pdf), str(out_file))
else:
print(f"跳过(已处理): {pdf.name}")
if __name__ == '__main__':
batch_process('./raw_docs', './processed_docs')
问题3:文档结构不适合检索
很多企业文档是这样写的:
第3章 员工福利
3.1 社会保险
3.2 住房公积金
3.3 补充商业保险
3.3.1 医疗险
3.3.2 意外险
这种结构对人读很友好,但切分成小块后,每块都丢失了上下文("这是关于哪个章节的?")。
解决方案:使用带上下文的切分策略(见 Level 2)。
在 Dify 中创建知识库
步骤一:创建分层知识库
不要把所有文档放入一个知识库,按部门和主题分库:
知识库结构:
├── kb-hr # HR 政策与流程
│ ├── 员工手册_v3.2.pdf
│ ├── 考勤管理制度.docx
│ └── 薪酬福利政策.pdf
├── kb-it # IT 系统操作
│ ├── ERP使用手册.pdf
│ ├── OA系统操作指南.pdf
│ └── IT安全规范.pdf
├── kb-product # 产品技术文档
│ ├── 产品规格书_系列A.pdf
│ └── 产品规格书_系列B.pdf
└── kb-quality # 质量与法规
├── ISO9001程序文件.pdf
└── 客户审核标准.pdf
步骤二:配置切分参数
在 Dify 知识库设置中:
分段规则:自动
最大分段长度:500 tokens(中文约 1000 字)
分段重叠:50 tokens(15% 重叠保证连贯性)
嵌入模型:text-embedding-ada-002(或 bge-large-zh-v1.5)
步骤三:配置检索参数
检索方式:混合检索(向量 + 关键词)
向量权重:0.7
关键词权重:0.3
召回数量:Top 5
相似度阈值:0.5
重排序:启用(使用 BGE Reranker)
Level 2:机制深解(3-5 年经验)
架构设计:多应用 + 路由层
该企业最终采用了"一个统一入口 + 多个专业助理"的架构:
用户入口(企业微信机器人 / 内部门户)
│
▼
路由层(Dify Workflow)
┌─────────────────────────┐
│ 意图识别: │
│ - HR 类问题 → HR 助理 │
│ - IT 类问题 → IT 助理 │
│ - 产品类 → 产品助理 │
│ - 质量类 → 质量助理 │
│ - 其他 → 通用助理 │
└─────────────────────────┘
│
┌─────┴─────┬──────────────┬──────────────┐
▼ ▼ ▼ ▼
HR 助理 IT 助理 产品助理 质量助理
(RAG) (RAG) (RAG) (RAG)
│ │ │ │
kb-hr kb-it kb-product kb-quality
路由 Workflow 配置:
# 路由工作流(Dify Workflow YAML 伪代码)
nodes:
- id: intent_classifier
type: llm
model: gpt-3.5-turbo # 路由用便宜模型
prompt: |
你是一个意图分类器。根据用户问题,判断属于以下哪个类别:
- HR:请假、报销、薪资、福利、社保、考勤、招聘
- IT:系统操作、账号权限、打印、网络、软件安装
- PRODUCT:产品参数、规格、技术指标、使用方法
- QUALITY:ISO认证、审核、质量标准、检验规程
- GENERAL:其他问题
只输出类别名称,不要解释。
用户问题:{{user_input}}
output_variable: intent
- id: router
type: if_else
conditions:
- variable: intent
value: HR
goto: hr_agent
- variable: intent
value: IT
goto: it_agent
- variable: intent
value: PRODUCT
goto: product_agent
- variable: intent
value: QUALITY
goto: quality_agent
- default:
goto: general_agent
RAG 参数精调
关键参数说明及调优建议:
| 参数 | 默认值 | 建议值(该企业) | 原因 |
|---|---|---|---|
| Chunk Size | 500 tokens | 400 tokens | 中文信息密度高,小 chunk 更精准 |
| Chunk Overlap | 50 tokens | 80 tokens | 制度文档有较多跨段落依赖 |
| Top K | 3 | 5 | HR 问题可能涉及多条规定 |
| 相似度阈值 | 0.5 | 0.6 | 提高精确度,减少噪音 |
| Reranker | 关闭 | 开启 | 显著提升排序质量 |
带上下文的切分策略(解决文档结构问题):
from langchain.text_splitter import RecursiveCharacterTextSplitter
from typing import List
class ContextualChunkSplitter:
"""带父文档上下文的切分器"""
def __init__(self, chunk_size=400, chunk_overlap=80):
self.splitter = RecursiveCharacterTextSplitter(
chunk_size=chunk_size,
chunk_overlap=chunk_overlap,
separators=["\n\n", "\n", "。", ";", ",", " ", ""]
)
def split_with_context(self, document: str,
title: str = "",
section: str = "") -> List[dict]:
"""
切分文档并保留章节上下文
Args:
document: 文档文本
title: 文档标题(如"员工手册")
section: 当前章节(如"第3章 员工福利")
"""
chunks = self.splitter.split_text(document)
enriched_chunks = []
for chunk in chunks:
# 在每个 chunk 前面加上上下文标头
context_header = f"文档:{title}\n章节:{section}\n\n"
enriched_chunk = context_header + chunk
enriched_chunks.append({
"text": enriched_chunk,
"metadata": {
"source_title": title,
"section": section,
"original_chunk": chunk
}
})
return enriched_chunks
Hybrid Search(混合检索)的内部原理:
Dify 的混合检索实际上是 BM25(关键词匹配)和向量搜索(语义相似度)的加权融合,使用 RRF(Reciprocal Rank Fusion)算法:
def reciprocal_rank_fusion(rankings: list, k: int = 60) -> list:
"""
RRF 融合多路检索结果
Args:
rankings: 多个排序列表 [[doc_id, ...], [doc_id, ...]]
k: 常数(控制高排名文档的权重,通常设为 60)
Returns:
融合后的排序列表
"""
scores = {}
for ranking in rankings:
for rank, doc_id in enumerate(ranking):
if doc_id not in scores:
scores[doc_id] = 0
# RRF 公式:1 / (k + rank)
scores[doc_id] += 1 / (k + rank + 1)
# 按融合分数降序排序
return sorted(scores.keys(), key=lambda x: scores[x], reverse=True)
System Prompt 工程
HR 助理的 System Prompt 经过 6 轮迭代,最终版本:
你是 [公司名] 的 HR 智能助理,负责回答员工关于公司政策、福利和流程的问题。
## 你的原则:
1. **仅基于提供的知识库内容回答**:如果知识库中没有相关信息,请明确说"我在知识库中找不到关于这个问题的信息,建议您直接联系 HR 部门"
2. **引用文档来源**:回答时注明信息来自哪个文档,例如"根据《员工手册》第3章..."
3. **给出完整流程**:对于涉及流程的问题(如请假、报销),必须完整列出每个步骤
4. **区分规则的绝对性**:明确区分"必须"(法规要求)和"建议"(公司倡导),不要混淆
5. **敏感问题转人工**:涉及个人薪资数据、绩效纠纷、劳动仲裁等敏感问题,引导员工联系 HR 专员
6. **语气专业友好**:使用礼貌、专业的语气,称呼用户为"您"
## 你不应该做的事:
- 猜测或推断政策(只能引用已有文档)
- 承诺任何例外或特殊处理
- 评价公司政策的合理性
- 透露其他员工的个人信息
API 集成:企业微信机器人
# enterprise_wechat_bot.py
# 将 Dify 接入企业微信机器人
import hashlib
import hmac
import time
import requests
from flask import Flask, request, jsonify
app = Flask(__name__)
DIFY_API_URL = "https://dify.yourcompany.com/v1"
DIFY_APP_TOKEN = "your-dify-app-token"
WECHAT_TOKEN = "your-wechat-verify-token"
WECHAT_ENCODING_AES_KEY = "your-aes-key"
# 维护会话映射(用户 ID → Dify 会话 ID)
# 生产环境建议用 Redis 存储
conversation_sessions = {}
@app.route('/wechat/callback', methods=['GET', 'POST'])
def wechat_callback():
if request.method == 'GET':
# 企业微信 URL 验证
return verify_wechat_url(request.args)
# 处理消息
data = parse_wechat_message(request.data)
if data['MsgType'] != 'text':
return reply_text(data['FromUserName'], "您好,目前仅支持文字消息")
user_id = data['FromUserName']
user_query = data['Content']
# 获取或创建 Dify 会话
conversation_id = conversation_sessions.get(user_id)
# 调用 Dify API
dify_response = call_dify_api(user_query, conversation_id)
# 保存会话 ID(支持多轮对话)
conversation_sessions[user_id] = dify_response.get('conversation_id')
answer = dify_response.get('answer', '抱歉,我暂时无法回答这个问题')
return reply_text(user_id, answer)
def call_dify_api(query: str, conversation_id: str = None) -> dict:
"""调用 Dify Chat API"""
headers = {
'Authorization': f'Bearer {DIFY_APP_TOKEN}',
'Content-Type': 'application/json'
}
payload = {
'inputs': {},
'query': query,
'response_mode': 'blocking', # 企业微信不支持流式
'conversation_id': conversation_id or '',
'user': 'enterprise_wechat'
}
response = requests.post(
f'{DIFY_API_URL}/chat-messages',
headers=headers,
json=payload,
timeout=30
)
return response.json()
def reply_text(to_user: str, content: str) -> str:
"""构造企业微信文本回复"""
timestamp = str(int(time.time()))
return f"""<xml>
<ToUserName><![CDATA[{to_user}]]></ToUserName>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[{content}]]></Content>
<CreateTime>{timestamp}</CreateTime>
</xml>"""
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080)
Level 3:源码与原理(5 年以上)
RAG 召回质量评估体系
上线后如何持续监控和改进 RAG 质量?需要建立一套评估体系:
评估指标:
| 指标 | 定义 | 计算方法 |
|---|---|---|
| 召回率 | 相关文档是否被检索到 | 相关文档召回数 / 相关文档总数 |
| 精确率 | 检索到的文档有多少是相关的 | 相关文档召回数 / 检索文档总数 |
| NDCG@K | 排序质量指标 | 考虑位置权重的归一化折损累积增益 |
| 答案忠实度 | 答案是否基于检索内容 | 人工标注 + LLM 自动评估 |
| 答案相关性 | 答案是否回答了问题 | 人工标注 + LLM 自动评估 |
自动评估脚本(基于 RAGAS 框架):
from ragas import evaluate
from ragas.metrics import (
faithfulness,
answer_relevancy,
context_recall,
context_precision,
)
from datasets import Dataset
def evaluate_rag_quality(test_cases: list) -> dict:
"""
评估 RAG 系统质量
Args:
test_cases: [
{
"question": "年假有几天?",
"contexts": ["根据员工手册,工龄1-10年员工享有5天年假..."],
"answer": "根据公司规定,工龄1-10年的员工享有5天年假...",
"ground_truth": "工龄1-10年5天,10年以上10天"
},
...
]
"""
dataset = Dataset.from_list(test_cases)
result = evaluate(
dataset,
metrics=[
faithfulness, # 忠实度:答案是否基于上下文
answer_relevancy, # 相关性:答案是否回答了问题
context_recall, # 召回率:上下文是否包含答案所需信息
context_precision, # 精确率:上下文中有多少是真正有用的
]
)
return result
# 构建标注测试集(最少 50 道题)
test_set = [
{
"question": "新员工试用期多长时间?",
"ground_truth": "根据岗位级别,技术岗3个月,管理岗6个月"
},
{
"question": "报销餐饮费用需要哪些单据?",
"ground_truth": "需要发票原件、报销申请单、就餐人员名单(3人以上需部门负责人签字)"
},
# ... 更多测试用例
]
# 每周自动运行评估
def weekly_quality_check():
# 1. 调用 Dify API 获取答案和检索上下文
for case in test_set:
response = call_dify_with_context(case['question'])
case['contexts'] = response['retrieval_documents']
case['answer'] = response['answer']
# 2. 评估
metrics = evaluate_rag_quality(test_set)
# 3. 如果指标下降超过 10%,触发告警
if metrics['faithfulness'] < 0.75:
send_alert(f"RAG 忠实度下降到 {metrics['faithfulness']:.2f}")
return metrics
文档更新的自动同步
HR 部门频繁更新政策文档,如何保证知识库及时更新?
# doc_sync.py — 文档变更自动同步到 Dify
import hashlib
import json
import os
from pathlib import Path
import requests
DIFY_API_URL = "https://dify.yourcompany.com/v1"
DIFY_DATASET_API_KEY = "dataset-api-key"
class DifyKnowledgeBaseSync:
def __init__(self, dataset_id: str):
self.dataset_id = dataset_id
self.state_file = f".sync_state_{dataset_id}.json"
self.state = self._load_state()
def _load_state(self) -> dict:
"""加载上次同步状态(文件哈希映射)"""
if os.path.exists(self.state_file):
with open(self.state_file) as f:
return json.load(f)
return {}
def _save_state(self):
with open(self.state_file, 'w') as f:
json.dump(self.state, f)
def _file_hash(self, file_path: str) -> str:
"""计算文件 MD5 哈希"""
with open(file_path, 'rb') as f:
return hashlib.md5(f.read()).hexdigest()
def sync_directory(self, docs_dir: str):
"""同步目录中的所有文档"""
docs_path = Path(docs_dir)
for doc_file in docs_path.glob('**/*'):
if not doc_file.is_file():
continue
if doc_file.suffix not in ['.pdf', '.docx', '.txt', '.md']:
continue
file_path = str(doc_file)
current_hash = self._file_hash(file_path)
if file_path not in self.state:
# 新文件:上传
print(f"新增文档: {doc_file.name}")
doc_id = self._upload_document(file_path)
self.state[file_path] = {
'hash': current_hash,
'dify_doc_id': doc_id
}
elif self.state[file_path]['hash'] != current_hash:
# 文件变更:删除旧版本,上传新版本
print(f"更新文档: {doc_file.name}")
old_doc_id = self.state[file_path]['dify_doc_id']
self._delete_document(old_doc_id)
new_doc_id = self._upload_document(file_path)
self.state[file_path] = {
'hash': current_hash,
'dify_doc_id': new_doc_id
}
# 检查已删除的文件
deleted_files = [
fp for fp in self.state.keys()
if not Path(fp).exists()
]
for fp in deleted_files:
print(f"删除文档: {fp}")
self._delete_document(self.state[fp]['dify_doc_id'])
del self.state[fp]
self._save_state()
def _upload_document(self, file_path: str) -> str:
"""上传文档到 Dify 知识库"""
with open(file_path, 'rb') as f:
response = requests.post(
f"{DIFY_API_URL}/datasets/{self.dataset_id}/document/create_by_file",
headers={'Authorization': f'Bearer {DIFY_DATASET_API_KEY}'},
files={'file': f},
data={
'data': json.dumps({
'indexing_technique': 'high_quality',
'process_rule': {
'mode': 'automatic'
}
})
}
)
return response.json()['document']['id']
def _delete_document(self, doc_id: str):
"""从知识库删除文档"""
requests.delete(
f"{DIFY_API_URL}/datasets/{self.dataset_id}/documents/{doc_id}",
headers={'Authorization': f'Bearer {DIFY_DATASET_API_KEY}'}
)
# 使用示例(配合 cron 定时运行)
if __name__ == '__main__':
syncer = DifyKnowledgeBaseSync(dataset_id='your-dataset-id')
syncer.sync_directory('/shared/hr-docs')
Level 4:生产陷阱与决策(专家视角)
上线前的验收测试清单
在正式向全员开放之前,必须通过以下验收测试:
功能测试(至少 50 个测试用例):
✅ 标准问题回答准确率 ≥ 90%
✅ 拒绝回答知识库外的问题(不编造)
✅ 多轮对话上下文保留(询问追问能正确理解)
✅ 歧义问题能主动澄清
✅ 敏感问题正确转人工
✅ 特殊字符、表情符号不导致崩溃
✅ 超长输入(> 2000 字)正确处理
性能测试:
# 使用 locust 做压力测试
# locustfile.py
from locust import HttpUser, task, between
import json
class DifyUser(HttpUser):
wait_time = between(1, 3)
@task
def chat(self):
headers = {
'Authorization': 'Bearer your-app-token',
'Content-Type': 'application/json'
}
payload = {
'inputs': {},
'query': '请假需要提前多少天申请?',
'response_mode': 'blocking',
'user': f'test_user_{self.user_id}'
}
self.client.post('/v1/chat-messages',
json=payload,
headers=headers)
# 运行压力测试:50 并发用户,运行 10 分钟
locust -f locustfile.py --headless \
-u 50 -r 5 \
--run-time 10m \
--host https://dify.yourcompany.com
预期性能指标(800 人企业,50 并发):
- P50 响应时间 < 3s
- P95 响应时间 < 8s
- 错误率 < 1%
- 每秒可处理请求 ≥ 20
上线后的 3 个月问题复盘
第 1 个月问题:用户不信任 AI 答案
现象:用户拿到 AI 的答案后,还是去找 HR 确认。
原因:答案中没有引用来源,用户无法判断可信度。
解决:修改 System Prompt,强制在每个答案末尾附上来源:
请在回答结尾以如下格式注明来源:
---
📄 信息来源:《员工手册》第 X 章(版本 v3.2,2024年1月生效)
如有疑问,请联系 HR 部门:[email protected] | 分机 1234
效果:用户满意度从 62% 提升到 81%。
第 2 个月问题:工艺文档检索不准
现象:产品规格书中有大量表格(材料参数、尺寸公差),检索时往往找不到准确数字。
原因:PDF 表格被转换为纯文字后,表格结构信息丢失,"硬度 HRC 60-62" 被解析为一行无意义文字。
解决:对技术文档使用专门的表格提取工具:
import camelot # 专为 PDF 表格提取设计
def extract_tables_from_pdf(pdf_path: str) -> str:
"""提取 PDF 中的所有表格,转换为 Markdown 格式"""
tables = camelot.read_pdf(pdf_path, pages='all', flavor='stream')
markdown_tables = []
for i, table in enumerate(tables):
df = table.df
# 转换为 Markdown 表格
md_table = df.to_markdown(index=False)
markdown_tables.append(f"## 表格 {i+1}\n{md_table}")
return '\n\n'.join(markdown_tables)
第 3 个月问题:多轮对话后答案质量下降
现象:用户进行 5 轮以上对话后,AI 开始"混乱",将第一轮的问题和最后一轮混在一起回答。
原因:随着对话历史增长,上下文窗口被占满,导致检索到的文档内容被压缩或丢弃。
解决:限制对话历史长度,并在系统层面自动总结:
# 对话历史管理策略
MAX_HISTORY_TOKENS = 2000 # 保留最近对话
def manage_conversation_history(history: list, max_tokens: int) -> list:
"""动态管理对话历史,防止超出上下文窗口"""
total_tokens = sum(estimate_tokens(msg) for msg in history)
if total_tokens <= max_tokens:
return history
# 策略:保留最近 3 轮对话 + 对早期对话做摘要
recent = history[-6:] # 最近 3 轮(每轮 user+assistant 共 2 条)
older = history[:-6]
if older:
# 对早期对话做摘要
summary = summarize_history(older)
summary_msg = {
'role': 'system',
'content': f'[早期对话摘要]\n{summary}'
}
return [summary_msg] + recent
return recent
知识库规模化的陷阱
陷阱:文档数量增长导致检索质量下降
当单个知识库文档数量超过 10,000 段时,会出现一个反直觉的现象:文档越多,检索精度越低。
原因:向量空间中文档太密集,导致相似度分数"压缩",很多文档的相似度都在 0.6-0.7 之间,难以区分。
解决方案:
1. 知识库分治:按业务领域严格分库,一个知识库不超过 5000 段
2. 提高相似度阈值:将 0.5 提高到 0.65,牺牲召回换精度
3. 添加元数据过滤:在检索时先用元数据(department、doc_type)过滤,再做向量检索
4. 定期清理:删除过期、重复的文档片段
# 带元数据过滤的检索
def filtered_retrieval(query: str, department: str, kb_id: str) -> list:
"""先过滤元数据,再做向量检索"""
results = vector_store.similarity_search(
query=query,
k=5,
filter={
"department": {"$eq": department},
"status": {"$eq": "active"} # 只检索生效中的文档
}
)
return results
本章小结
完整项目时间线(供参考):
| 阶段 | 时间 | 关键产出 |
|---|---|---|
| 需求调研 | 第 1-2 周 | 问题清单、优先级排序 |
| 文档治理 | 第 3-4 周 | 清洁的文档库、版本控制规范 |
| 知识库构建 | 第 5-6 周 | 4 个知识库,文档完成索引 |
| 应用开发 | 第 7-9 周 | Dify 应用配置、集成开发 |
| 测试与调优 | 第 10-11 周 | 通过验收测试,优化参数 |
| 小范围试运行 | 第 12 周 | 邀请 50 人试用,收集反馈 |
| 全员上线 | 第 13-14 周 | 全员开放,配套培训 |
| 持续迭代 | 持续 | 每周分析数据,每月更新知识库 |
核心成功要素:
- 文档质量优先:70% 的 RAG 质量问题来自文档本身(过期、格式差、结构混乱)。
- 分域知识库:按业务领域严格分库,不要贪图"一库解决所有问题"。
- 持续评估:建立 Golden Set 测试用例,每周自动评估检索质量。
- 用户反馈闭环:必须有"这个答案有帮助吗?"的反馈机制,不断优化。
- 人工兜底:永远保留"找到真人"的出口,AI 不应成为用户的最后一道墙。