ollama本地大模型知识库智能客服搭建指南
摘要
通过Ollama在本地部署大模型,结合自建知识库,利用LangChain等工具构建智能客服系统。全过
本地部署智能客服:Ollama + 私有知识库完整方案
数据安全始终是AI落地的核心瓶颈。大型语言模型能力再强,一旦每次对话都需要将数据上传至云端,许多注重隐私的企业便难以迈出关键一步。幸运的是,当前的技术方案已足够成熟:借助Ollama在本地服务器部署大模型,再结合自建的私有知识库,完全能够在数据不出内网的前提下,构建一套高效、高度定制化的智能客服系统。本文将从零开始拆解整个实施流程,为正在选型或推动落地的团队提供可复用的实操参考。

1. 背景与动机
1.1 Ollama:本地大模型运行框架
Ollama是一个开源项目,其核心价值在于极大简化了本地部署与运行大模型的过程。通过它,企业无需将数据输出到云端,直接在自有服务器上即可运行Llama系列等主流模型,数据的隐私与可控性完全由自己掌握。安装步骤因操作系统而异,网上有详尽的文档,按指引操作即可。
1.2 私有知识库:智能客服的精准度基石
智能客服能否给出精准回答,取决于背后是否有一套“懂行业”的私有知识库。所谓私有知识库,就是将公司内部的FAQ、产品手册、客服政策等数据全部存放于自有服务器,形成专属知识集合。与云端知识库相比,私有化部署的最大优势在于权限可控、数据不外泄,敏感信息的合规性得到根本保障。
2. 系统架构解析
2.1 技术栈
整个系统依赖以下核心组件:
● Ollama:本地模型运行环境,负责模型加载与推理。
● LangChain:关键编排工具,负责知识库内容的拆分、向量化,并将检索与LLM串联成完整的问答链路。
● Embedding:嵌入技术将文本转换为机器可理解的数学坐标(向量)。通过计算向量间的相似度,系统能快速从知识库中召回与用户问题最相关的片段。
2.2 工作流程
系统运作流程清晰,分为以下几步:
- 数据预处理:对知识库文档进行清洗、切分并建立索引。
- 用户提问:用户通过前端界面提交问题。
- 请求解析:API网关接收请求并完成解析。
- 知识检索:系统根据问题在本地知识库中匹配最相关的信息段落。
- 模型推理:Ollama结合用户问题和检索内容生成精准回答。
- 结果返回:最终答案经API网关返回前端展示。
3. 实战部署全流程
3.1 模型下载
本次使用的Embedding模型为 bce-embedding-vase_v1。下载时需关注网络环境:若服务器能直接访问外网,使用git命令拉取即可;若网络受限,则需进入模型官方页面的“Files and versions”标签页,按目录结构逐个手动下载至本地。例如,我将模型存放于 D:vecbce-embedding-vase_v1 路径下。
3.2 构建本地知识库
构建知识库的第一步是准备原始文档。以下是一个常见的Git问题FAQ示例:
问题1:git克隆失败-文件名太长答案1:查看错误信息中是否包含关键字:Filename too long问题2:git克隆失败-access_token失效答案2:查看错误信息中是否包含关键字:Authentication failed for、 Access denied、invalid_token。解决方法:重新生成一个有效的access_toekn问题3:git克隆失败-网络超时答案3:查看错误信息中是否包含关键字:Connection timed out、Unknown error、Could not resolve host等。可能是执行机与yfgitlab网络不通或者网络波动导致,执行机dns配置有问题,不能访问yfgitlab的域名问题4:git克隆失败-CI站点上配置的工程信息异常答案4:查看错误信息中是否包含关键字:FETCH_HEAD error: Sparse checkout lea ves no entry on working directory。可能原因:1)、工程信息中填写的脚本路径斜杠反了,比如不正确的写法:TESTStabilityITC,正确的写法:TEST/Stability/ITC;2)多个脚本路径用英文分号拼接,不能使用其他符号,比如TEST/PI/SD,TEST/PI/COMMON使用逗号拼接的是异常的问题5:git克隆失败-‘git’ 不是内部或外部命令,也不是可运行的程序答案5:1、检查下执行机上是否安装了git;2、可能链接jenkins的时候没有安装git,链接成功后才安装的git,联系工厂客服删除节点,用户重新部署执行机。问题6:git克隆失败-分支名中带有.号答案6:查看错误信息中是否包含关键字:Invalid argument Cloning into 。换一个没有.号的分支名问题7:git克隆失败-git链接不是以.git结尾答案7:查看错误信息中是否包含关键字:没有找到项目名称(xxx)对应的项目id。需要填写完整的git地址问题8:git克隆失败-out of memory答案8:查看错误信息中是否包含关键字:out of memory、No space left on device。用户需要检查下执行机硬盘空间
文档准备完成后,下一步是将其转化为向量数据库。代码如下:
# coding=utf-8
from langchain_community.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.embeddings importHuggingFaceEmbeddings
from langchain_community.vectorstores import Chroma
from langchain_community.llms import Ollama
from langchain.chains import RetrievalQA
# 导入文本
loader = TextLoader(r"D:vecdocumenttest.txt")
# 将文本转成 Document 对象
data = loader.load()
print(f'documents:{len(data)}')
# 初始化加载器
text_splitter = RecursiveCharacterTextSplitter(chunk_size=100, chunk_overlap=0)
# 切割加载的 document
split_docs = text_splitter.split_documents(data)
print("split_docs size:",len(split_docs))
model_name = r"D:vecbce-embedding-vase_v1"
model_kwargs = {'device': 'cpu'}
encode_kwargs = {'normalize_embeddings': False}
embeddings = HuggingFaceEmbeddings(
model_name=model_name,
model_kwargs=model_kwargs,
encode_kwargs=encode_kwargs
)
# 保存向量数据库部分
# 初始化数据库
db = Chroma.from_documents(split_docs, embeddings, persist_directory=r"D:vecvecdb")
# 持久化
db.persist()
# 对数据进行加载
db = Chroma(persist_directory=r"D:vecvecdb", embedding_function=embeddings)
question = "out of memory"
# 测试寻找四个相似的样本
similarDocs = db.similarity_search(question,k=4)
3.3 集成Ollama与知识库
知识库构建完成后,与Ollama的集成只需一行核心代码。LangChain的RetrievalQA链直接串联检索与问答:
# coding=utf-8
from langchain_community.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.embeddings importHuggingFaceEmbeddings
from langchain_community.vectorstores import Chroma
from langchain_community.llms import Ollama
from langchain.chains import RetrievalQA
retriever = db.as_retriever()
qa = RetrievalQA.from_chain_type(llm=Ollama(base_url='http://XX.XX.XX.XXX:9999',model="Qwen2-7b:latest"),retriever=retriever)
query = "我在做持续集成的时候,发现在git克隆的时候出现out of memory"
print(qa.run(query))
3.4 开发前后端
为便于演示,将训练、检索与接口封装在同一文件中。后端基于Flask提供简单API:
from flask import Flask, request, jsonify
from flask_cors import CORS
# 上面的代码保持不变
from langchain_community.document_loaders import TextLoader
from langchain_huggingface import HuggingFaceEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import Chroma
from langchain_community.llms import Ollama
from langchain.chains import RetrievalQA
# 导入文本
loader = TextLoader(r"D:vecdocumenttest.txt")
data = loader.load()
print(f'documents:{len(data)}')
text_splitter = RecursiveCharacterTextSplitter(chunk_size=100, chunk_overlap=0)
split_docs = text_splitter.split_documents(data)
print("split_docs size:", len(split_docs))
model_name = r"D:vecbce-embedding-vase_v1"
model_kwargs = {'device': 'cpu'}
encode_kwargs = {'normalize_embeddings': False}
embeddings = HuggingFaceEmbeddings(
model_name=model_name,
model_kwargs=model_kwargs,
encode_kwargs=encode_kwargs
)
db = Chroma.from_documents(split_docs, embeddings, persist_directory=r"D:vecvecdb")
db.persist()
db = Chroma(persist_directory=r"D:vecvecdb", embedding_function=embeddings)
retriever = db.as_retriever()
qa = RetrievalQA.from_chain_type(llm=Ollama(base_url='http://xx.xx.xxx.xxx:9999', model="Qwen2-7b:latest"), retriever=retriever)
# 创建FastAPI应用
app =Flask(__name__)
CORS(app)
@app.route('/query', methods=['POST'])
async def query_endpoint():
# 使用qa.run处理请求中的查询
data = request.get_json()
messages = data.get('query')
result = qa.run(messages)
return jsonify({"response": result})
if __name__ == '__main__':
app.run(debug=True)
前端采用基础HTML页面,包含输入框与展示区,支持Markdown渲染:
Chat Interface with Markdown
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/4.2.12/marked.min.js"></script>
<script>
function sendMessage() {
const userInput = document.getElementById('userInput');
const chatHistory = document.getElementById('chatHistory');
// 获取用户输入并清空输入框
const userMessage = userInput.value;
userInput.value = '';
// 构建请求体
const data = {
"query": userMessage
};
// 发送POST请求到后端接口
fetch('http://127.0.0.1:5000/query', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(data => {
// 假设后端返回的数据格式为 { "response": "回答内容" }
const botResponse = data.response;
// 在聊天历史中添加用户的问题
chatHistory.innerHTML += `你: ${userMessage}
`;
// 将Markdown转换为HTML并添加机器人的回答
if (botResponse) {
const htmlResponse = marked.parse(botResponse);
chatHistory.innerHTML += `机器人: ${htmlResponse}
`;
} else {
console.error("没有从后端接收到有效的回答");
}
// 滚动到底部以便查看最新消息
chatHistory.scrollTop = chatHistory.scrollHeight;
})
.catch(error => {
console.error('Error:', error);
// 可以在这里添加错误信息的展示逻辑
chatHistory.innerHTML += `错误: 发生了一个错误,请稍后再试。
`;
});
}
</script>
3.5 测试
启动后端服务后,在前端输入“分支名中带有.号”,系统立即从本地知识库召回匹配答案。整个交互过程流畅,数据全程未离开本地环境。
4. 安全与维护
方案落地后,运维环节不可忽视。几个关键点:
● 数据加密:知识库中的敏感数据必须加密存储。
● 访问控制:严格权限管理,明确谁可以使用、能用哪些数据。
● 定期更新:Ollama及其依赖库版本迭代较快,及时更新既能获得新特性,也能规避已知安全漏洞。
5. 结论
通过Ollama结合私有知识库,企业能够构建一套既充分发挥大模型能力、又具备高度自主可控性的智能客服系统。该方案在数据安全、响应延迟与定制化深度上均有显著优势。伴随技术栈的持续成熟,本地化部署的智能客服系统将在企业数字化转型中扮演越来越务实的角色。
来源:互联网
本网站新闻资讯均来自公开渠道,力求准确但不保证绝对无误,内容观点仅代表作者本人,与本站无关。若涉及侵权,请联系我们处理。本站保留对声明的修改权,最终解释权归本站所有。