钉钉 AI 客服:RAG 架构设计
RAG 是 AI 客服的核心架构。
一、RAG 概念
Retrieval-Augmented Generation:检索增强生成
用户问题 → 检索相关文档 → 组合提示词 → AI 生成回答
二、架构设计
┌─────────────────────────────────────────────┐
│ 用户问题 │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 问题理解 │
│ - 意图识别 │
│ - 实体提取 │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 文档检索 │
│ - 向量检索 │
│ - 关键词检索 │
│ - 混合检索 │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 重排序 │
│ - 相关性评分 │
│ - 多样性过滤 │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ LLM 生成 │
│ - 提示词组合 │
│ - 答案生成 │
└─────────────────────────────────────────────┘
三、文档处理
3.1 文档分割
function splitDocument(text, chunkSize = 500) {
const chunks = [];
for (let i = 0; i < text.length; i += chunkSize) {
chunks.push(text.slice(i, i + chunkSize));
}
return chunks;
}
3.2 向量化存储
async function indexDocument(doc) {
const chunks = splitDocument(doc.content);
for (const chunk of chunks) {
const vector = await embed(chunk);
await storeVector(vector, {
docId: doc.id,
content: chunk
});
}
}
四、检索优化
4.1 多路召回
async function retrieve(question) {
// 向量检索
const vectorResults = await vectorSearch(question, 10);
// 关键词检索
const keywordResults = await keywordSearch(question, 10);
// 融合
return mergeAndRerank(vectorResults, keywordResults);
}
4.2 重排序
async function rerank(question, documents) {
const scores = await Promise.all(
documents.map(doc => computeRelevance(question, doc))
);
return documents
.map((doc, i) => ({ doc, score: scores[i] }))
.sort((a, b) => b.score - a.score)
.slice(0, 5);
}
五、提示词组合
function buildPrompt(question, contexts) {
return `
基于以下知识回答用户问题:
${contexts.map(c => c.content).join('\n\n')}
用户问题:${question}
要求:简洁准确,不超过 100 字。
`;
}
六、效果优化
| 优化点 | 方法 |
|---|---|
| 召回率 | 多路召回 |
| 准确率 | 重排序 |
| 响应速度 | 缓存 |
| 成本 | 模型选择 |
项目地址:GitHub - dingtalk-connector-pro 有问题欢迎 Issue 或评论区交流