从零搭建一个智能客服机器人

2026-06-07 · 阅读约 15 分钟

智能客服已经是现代企业的标配——但购买成熟的SaaS方案动辄年费数万甚至数十万,对于中小团队来说成本太高。好在,借助开源工具和LLM(大语言模型),你完全可以用很低的成本搭建一个功能强大的智能客服机器人。

本文使用纯开源技术栈,手把手带你从零实现。

一、整体架构设计

我们的智能客服机器人采用经典 RAG(检索增强生成)架构:

用户提问
   │
   ▼
┌─────────────────┐
│  前端对话界面     │  ← Web / 小程序 / 钉钉 / 企微
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│  API 网关        │  ← FastAPI / Flask
└────────┬────────┘
         │
    ┌────┴────┐
    │         │
    ▼         ▼
┌────────┐ ┌────────────┐
│ LLM    │ │ 向量数据库  │  ← ChromaDB / Qdrant / Milvus
│ 模型   │ │ (知识库)    │
└────────┘ └────────────┘

核心组件说明:

二、准备工作

环境要求:

安装依赖:

pip install langchain langchain-community chromadb fastapi uvicorn
pip install openai  # 如果使用OpenAI兼容API
# 或使用开源模型
pip install llama-cpp-python  # 本地运行GGUF模型

三、搭建知识库 (RAG 核心)

知识库是智能客服的大脑。把你企业的常见问题(FAQ)、产品文档、操作手册整理成文档,存入向量数据库。

3.1 准备知识文档

创建一个 knowledge_base/ 目录,放入MD或TXT格式的文档。例如:

knowledge_base/
├── 常见问题.md
├── 退款政策.md
├── 产品使用指南.md
└── 技术支持联系.md

3.2 文档嵌入与存储

from langchain.document_loaders import DirectoryLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Chroma

# 1. 加载文档
loader = DirectoryLoader("knowledge_base/", glob="**/*.md")
documents = loader.load()

# 2. 文档分块
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,
    chunk_overlap=50
)
chunks = text_splitter.split_documents(documents)

# 3. 生成向量并存储
embeddings = OpenAIEmbeddings()  # 或使用开源嵌入模型
vectorstore = Chroma.from_documents(
    documents=chunks,
    embedding=embeddings,
    persist_directory="./chroma_db"
)
vectorstore.persist()
print(f"知识库已构建完成,共 {len(chunks)} 个文档片段")

四、构建问答引擎

使用LangChain的检索问答链实现核心问答功能:

from langchain.chains import RetrievalQA
from langchain.chat_models import ChatOpenAI
from langchain.prompts import PromptTemplate

# 加载已构建的向量数据库
embeddings = OpenAIEmbeddings()
vectorstore = Chroma(
    persist_directory="./chroma_db",
    embedding_function=embeddings
)

# 自定义提示词模板
prompt_template = """你是一个专业的客服助手。请基于以下已知信息回答用户的问题。
如果已知信息不足以回答问题,请说"我无法从现有知识库中找到答案",
不要编造信息。

已知信息:
{context}

用户问题:{question}

请用友好的语气回答,保持简洁有条理。如果涉及操作步骤,请用编号列出。
回答:"""

qa_chain = RetrievalQA.from_chain_type(
    llm=ChatOpenAI(model="gpt-3.5-turbo", temperature=0),
    chain_type="stuff",
    retriever=vectorstore.as_retriever(search_kwargs={"k": 4}),
    chain_type_kwargs={
        "prompt": PromptTemplate(
            template=prompt_template,
            input_variables=["context", "question"]
        )
    }
)

# 测试
response = qa_chain.run("如何申请退款?")
print(response)

五、API 服务层

用 FastAPI 包装成 HTTP 接口:

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import uvicorn

app = FastAPI(title="智能客服API")

class Query(BaseModel):
    question: str
    session_id: str | None = None

class Response(BaseModel):
    answer: str
    sources: list[str] = []

# 会话历史存储(生产环境请用Redis)
sessions = {}

@app.post("/api/chat", response_model=Response)
async def chat(query: Query):
    try:
        # 获取或创建会话历史
        history = sessions.get(query.session_id, [])

        # 调用问答引擎
        result = qa_chain.invoke({
            "query": query.question,
            "chat_history": history
        })

        # 更新会话历史
        history.append((query.question, result["result"]))
        if query.session_id:
            sessions[query.session_id] = history[-10:]  # 保留最近10轮

        return Response(
            answer=result["result"],
            sources=[doc.metadata.get("source", "") for doc in result["source_documents"]]
        )
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)

六、前端对话界面

用纯HTML/JS快速搭建一个对话界面(可直接嵌入到现有网站):

<!-- chatbot-widget.html -->
<div id="chatbot-widget">
  <div id="chatbot-header">
    🤖 智能客服
    <button onclick="toggleChat()">×</button>
  </div>
  <div id="chatbot-messages"></div>
  <div id="chatbot-input">
    <input type="text" id="chat-input" placeholder="输入您的问题..." />
    <button onclick="sendMessage()">发送</button>
  </div>
</div>

<script>
const sessionId = 'session_' + Date.now();

async function sendMessage() {
  const input = document.getElementById('chat-input');
  const msg = input.value.trim();
  if (!msg) return;

  addMessage(msg, 'user');
  input.value = '';

  const res = await fetch('/api/chat', {
    method: 'POST',
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify({ question: msg, session_id: sessionId })
  });
  const data = await res.json();
  addMessage(data.answer, 'bot');
}

function addMessage(text, role) {
  const container = document.getElementById('chatbot-messages');
  const div = document.createElement('div');
  div.className = 'message ' + role;
  div.textContent = text;
  container.appendChild(div);
  container.scrollTop = container.scrollHeight;
}
</script>

七、部署与调优

部署方案

调优技巧

  1. 优化文档分块策略 — 根据文档类型调整chunk_size(FAQ用200字,产品文档用500字)
  2. 设置相似度阈值 — 只有当检索得分高于阈值时才使用检索结果,否则让模型直说不知道
  3. 添加反问机制 — 当用户提问模糊时,AI应该反问澄清而不是瞎猜
  4. 限流与安全 — 添加频率限制、敏感词过滤、Prompt注入防护
  5. 人工兜底 — 当AI连续3次无法回答或用户要求"转人工"时,自动创建工单转接人工客服

八、总结

本文搭建的智能客服机器人使用了纯开源技术栈,虽然功能上可能无法100%对标销售SaaS产品,但对于大多数中小团队来说已经足够使用。更重要的是——数据完全掌握在自己手中,没有第三方泄露风险。

从知识库构建,到RAG引擎,再到API和前端,整套方案可在一两天内完成搭建。现在就开始吧!

← 返回实战宝典首页