首页 > 教程攻略 > ai资讯 >浅谈人工智能之基于ollama本地大模型结合本地知识库搭建智能客服

浅谈人工智能之基于ollama本地大模型结合本地知识库搭建智能客服

来源:互联网 时间:2026-06-13 13:50:07

摘要

在AI这件事上,数据安全始终是一个绕不开的话题。大模型再厉害,如果每次对话都要把数据传输到云端,对很多注重隐私的企业来说,这步子根本就迈不出去。好在,技术方案已经足够成熟了。利用Ollama在本地部署大模型,再结合自建的知识库,完全可以在保障数据不出门的前提下,搭建一个高效、定制化的智能客服系统。这篇内容,就是把从零开始的完整过程拆开来讲,希望能给正在选型或落地的团队一些实实在在的参考。

浅谈人工智能之基于ollama本地大模型结合本地知识库搭建智能客服

1. 引言

1.1 Ollama简介

先说说Ollama。它是一个开源项目,核心价值就是让本地部署和运行大模型这件事变得特别简单。有了它,你不用把数据送到云端,直接在本地服务器上就能跑Llama系列等主流模型,数据的隐私和可控性完全掌握在自己手里。安装过程就不展开了,不同的操作系统有对应的部署方式,网上资料很全,按步骤来就好。

1.2 本地知识库的重要性

智能客服能不能回答得准,核心在于它背后有没有一套“懂行”的知识库。所谓本地知识库,说白了,就是把公司内部的FAQ、产品手册、客服政策这些数据,全部存在自己的服务器上,形成一个专门的知识集合。跟放在云端的方案相比,本地知识库最大的优势就是权限可控、数据不外流,敏感信息的安全性有了根本保障。

2. 系统架构概述

2.1 技术栈

整个系统主要依赖几个组件:

Ollama

:作为本地模型的运行环境,负责加载和推理。

LangChain

:这是一个非常重要的编排工具。它的任务很简单,就是负责把知识库里的内容做拆分、向量化,然后把检索和LLM串起来,形成一个完整的问答流程。

Embedding

:嵌入技术,可以理解为把文字翻译成机器能理解的数学坐标(也就是向量)。通过计算向量之间的相似度,系统才能快速从知识库里找到跟用户问题最相关的内容。

2.2 工作流程

整个系统的运作流程其实并不复杂,可以分为几个清晰的步骤:

  1. 模型训练

    :对准备的知识库数据进行初步处理和索引构建。
  2. 用户提问

    :用户通过前端界面提交问题。
  3. 请求处理

    :API网关接收请求,并做解析。
  4. 知识检索

    :系统根据问题,在本地知识库中检索最相关的信息片段。
  5. 模型推理

    :Ollama结合用户的问题和检索到的知识,生成精准的回答。
  6. 结果返回

    :最终答案通过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加本地知识库这条路,企业完全可以构建一套既能充分发挥大模型能力、又具备高度自主可控性的智能客服系统。这种方案在数据安全、响应速度和定制化程度上都有明显优势。从实际落地的角度来看,随着整个技术栈的不断成熟,本地部署的智能客服系统会越来越普及,也会成为企业数字化转型过程中一个非常务实的选择。

相关下载