deepseek + embeding模型搭建本地知识库

上一篇文章讲了ollama+deepseek模型的本地化部署,具体能部署哪一款取决于你的土豪程度:
在这里插入图片描述
今天的目标是本地安装部署embeding模型,实现LLM+embeding模型的rag知识库的本地化部署,包括:

  1. embeding模型的本地化部署
  2. anyhingLLM安装配置,使用本地LLM和embeding模型实现知识库
  3. api方式调用本地deepseek模型及emeding模型实现本地知识库

emeding模型的本地化部署

ollama官网上embeding排名比较靠前的两个:

  1. ollama pull nomic-embed-text
  2. bge-m3

安装当然非常简单,通过ollama官网copy命令:
在这里插入图片描述

或者直接命令行输入:

ollama pull bge-m3

安装完成之后,验证一下:
在这里插入图片描述
说明bge-m3和nomic-eded-text两个embeding模型已经完成了本地安装。

安装anythingLLM并配置LLM模型

直接到官网下载:
https://anythingllm.com/

anything有两个不同的版本,desktop是创建 all-in-one AI application的桌面版本,顾名思义,是个人桌面型工具,只能给你个人提供AI应用的帮助。另外一个可以docker部署的服务器版本,是可以支持团队应用的,部署后支持用户管理、权限管理,可以作为服务端为多个用户提供服务。
在这里插入图片描述
今天我们下载安装桌面版。

下载完成后,配置也非常简单。

首先点击左下角这个扳手进行配置:
在这里插入图片描述
如果要用本地安装的deepseek模型,在LLM提供商处选择ollama:

在这里插入图片描述
modal选择你安装的模型,我本机只有一个deepseek-r1:1.5b(比较穷),下面127.0.0.1:11434,就是本地ollama的服务端口,其他参数保持默认即可。

LLM模型配置之后就可以开始对话了,当然,anythingLLM在对话之前需要创建workplace,很简单,给个名字就完成了创建。

需要注意,对话之前本地的模型需要先启动起来。如果不启动模型直接对话,我猜测是anythingLLM在胡乱回答问题:
在这里插入图片描述
然后,启动本地模型:
在这里插入图片描述

然后再对话:
在这里插入图片描述

配置embeding模型

接下来我们配置下embeding模型,尝试下用anythingLLM创建本地RAG知识库,embeder首选项配置,选择bge-m3:

在这里插入图片描述
embeding模型就配置好了,可以使用了。

上传文档

点击工作区右侧的上传文档小图标打开文档上传窗口,上传文档完成后,拖入到下方的工作区中,系统需要embeding你上传的文档,根据你个人机器的配置情况以及文档大小,embeding可能需要点时间:
在这里插入图片描述

embeding之后就可以使用知识库了,我上传了两个word文档,测试了一下效果,确实,不得不说,效果很差。

我说效果差的意思是,我提问上传文档中的相关问题,他的回答很难命中文档中的内容。

相同的文档,相同的问题,我在deepseek官网上做了测试,deepseek官网能非常完美的回答问题。

效果差当然有可能得两个主要原因,一个就是embeding模型或向量数据库的问题,召回不准确。另外一个就是LLM的问题,虽然能准确从向量数据库召回,但是送给大模型之后,获取不到正确的回答。

这个问题不难验证:
修改anythingLLM的LLM首选项,改变LLM为deepseek线上模型(不用本地的穷鬼模型了):
在这里插入图片描述
当然,你需要首先从deepseek官网获得APIKey。

同样的问题,本地1.5b模型的回答是:
在这里插入图片描述
这就是在胡扯,因为我上传的的文档中有描述:
在这里插入图片描述
更换为线上模型后:
在这里插入图片描述
回答应该是接近完美了。

通过API方式搭建本地知识库

除了以上anythingLLM等AI工具搭建本地知识库外,程序员最感兴趣的、或者最有可能接入你的应用、为你的用户提供基于LLM的本地知识库解决方案的方式,个人认为还是通过coding、API的方式调用本地LLM以及embeding模型。

上一篇文章已经说过了怎么通过API方式调用ollama接口从而调用本地deepseek模型,今天我们结合bge-m3的api、通过加载pdf文档创建本地知识库,并调用本地deepseek模型进行问答,完成本地rag系统的搭建。

用cursor,不会就问,我本来也不太懂python,但是有了cursor,加上其他编程语言的经验,你就可以秒变python专家(当然是吹牛B了哈哈,这是好多培训机构的话术,是为了掏空你腰包的)。不过在cursor的帮助下,python新手也能完成相对比较复杂的代码。

首先把pdf文件读进来:

from pdfminer.high_level import extract_pages
from pdfminer.layout import LTTextContainer

def extract_text_from_pdf(filename, page_numbers=None, min_line_length=1):
    paragraphs = []
    buffer = ''
    full_text = ''
    for i, page_layout in enumerate(extract_pages(filename)):
        if page_numbers is not None and i not in page_numbers:
            continue
        for element in page_layout:
            if isinstance(element, LTTextContainer):
                full_text += element.get_text() + '\n'
    lines = full_text.split('\n')
    for text in lines:
        if len(text) >= min_line_length:
            buffer += (' '+text) if not text.endswith('-') else text.strip('-')
        elif buffer:
            paragraphs.append(buffer)
            buffer = ''
    if buffer:
        paragraphs.append(buffer)
    return paragraphs

pdf_path = os.path.join(script_dir, "llama2.pdf")

paragraphs = extract_text_from_pdf("llama2.pdf", min_line_length=10)

然后创建LLM模型调用的相关代码:

from openai import OpenAI
import os
from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv())  

client = OpenAI()

# def get_completion(prompt, model="deepseek-r1:1.5b"):
def get_completion(prompt, model="deepseek-reasoner"):
    messages = [{"role": "user", "content": prompt}]
    response = client.chat.completions.create(
        model=model,
        messages=messages,
        temperature=0,  
    )
    return response.choices[0].message.content

def build_prompt(prompt_template, **kwargs):
    inputs = {}
    for k, v in kwargs.items():
        if isinstance(v, list) and all(isinstance(elem, str) for elem in v):
            val = '\n\n'.join(v)
        else:
            val = v
        inputs[k] = val
    return prompt_template.format(**inputs)

embeding之后计算余弦距离的函数,用来测试embeding模型是否能成功调用:

def cos_sim(a, b):
    return dot(a, b)/(norm(a)*norm(b))


def l2(a, b):
    x = np.asarray(a)-np.asarray(b)
    return norm(x)  

然后是embeding模型调用的代码,通过ollama模块调用本地安装的bge-m3模型:

def get_embeddings(texts, model="bge-m3", dimensions=None):
    data = []
    for ele in texts:
        data.append( ollama.embeddings(model=model,
                         prompt=ele))
    return [x.embedding for x in data]

然后随便写一段话就可以测试了:

query = "程序员往往需要996"

documents = [
    "程序员的工作非常辛苦,常常需要加班",
    "编写脚本拍一段视频其实也很简单的",
    "AI可以代替绝大部分计算机操作人员的工作",
    "圆明园游客非常多",
    "清华大学deepseek从入门到精通",
]

query_vec = get_embeddings([query])[0]
doc_vecs = get_embeddings(documents)

print("Query与自己的余弦距离: {:.2f}".format(cos_sim(query_vec, query_vec)))
print("Query与Documents的余弦距离:")
for vec in doc_vecs:
    print(cos_sim(query_vec, vec))

如果以上代码能运行正常,说明本地embeding模型已经成功调用了。

在这里插入图片描述
接下来,加载pdf文档的内容,embeding之后写入向量数据库:

# 创建一个向量数据库对象
vector_db = MyVectorDBConnector("demo", get_embeddings)
# 向向量数据库中添加文档
vector_db.add_documents(paragraphs)

创建一个对话机器人:

class RAG_Bot:
    def __init__(self, vector_db, llm_api, n_results=2):
        self.vector_db = vector_db
        self.llm_api = llm_api
        self.n_results = n_results

    def chat(self, user_query):
        # 1. 检索
        search_results = self.vector_db.search(user_query, self.n_results)

        # 2. 构建 Prompt
        prompt = build_prompt(
            prompt_template, context=search_results['documents'][0], query=user_query)

        # 3. 调用 LLM
        response = self.llm_api(prompt)
        return response
    # 创建一个RAG机器人
bot = RAG_Bot(
    vector_db,
    llm_api=get_completion
)

user_query = "llama 2有多少参数?"

response = bot.chat(user_query)

print(response)

调用本地deepseek r1:1.5b模型的回答:
在这里插入图片描述
与anythingLLM的方式调用本地模型一样,效果不能令人满意。

同样,我们更换一下线上模型试试看,对pdf的读取方式不变,还是用本地的embeding模型,结果:
在这里插入图片描述
代码中可以打印一下召回文本的内容,发现确实不是召回的问题,而是召回后发送给模型之后,本地的1.5b模型确实能力不足,导致回答不能令人满意。

为什么要本地部署

我在做本地部署的时候其实并没有想过这个问题,作为一名技术人员,尤其是程序员,对技术问题持的好奇心其实是天性使然。所以,为什么要进行本地部署就不会是一个问题:因为它支持本地部署,使用ollama进行本地部署后,ollama本身还提供了类openai的接口api,那我为什么不试一下?

所以为什么不做本地部署才会是一个问题。

但是这几天确实太疯狂了,打开浏览器、微信公众号等等所有的媒体,铺天盖地全是deepseek的信息,也有很多本地部署的信息,确实有很多人把本地部署当做一项特殊技能,跃跃欲试要给客户提供相关服务了。对于传统IT公司来讲,这可能会是一个机会,但个人认为绝不会是一个什么稍纵即逝的机会,也不是什么只要你提前布局就能提前把握住的新机会,如果说LLM或者RAG知识库能给客户提供新的巨大帮助的话,也需要服务商具有深厚的IT服务基本功,需要认真考量其与企业现有数字化能力、数字化水平、数字化基础的对接方式,需要有扎扎实实大量的投入,才有可能找到合适的落地方案。

从这个角度讲,我们做本地部署的目的,最主要的其实还是学习,包括不同体量的模型的能力,模型的API调用,尝试LLM模型、embeding模型与现有系统的对接,测试模型的funcation calling能力等等。做了本地化部署其实是可以方便进行这类对接测试的,除了省钱之外,还能避免“服务器繁忙”的坑。

毕竟,本地部署满血模型是很烧银子的,而除了满血模型,从网上大部分本地部署后的反馈来看,即使是70b的模型效果也就差强人意…所以,本地部署后要应用的,需三思。

以上。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/970239.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2、树莓派5第一次开机三种方式:使用外设 / 使用网线 / 使用wifi

本文整理了树莓派第一次开机方式,供大家参考 方式一:连接鼠标、键盘、显示器外设开机 树莓派自带USB接口及HDMI接口,因此可以通过USB连接鼠标键盘,HDMI接入显示器,再进行电源供电,就可以完成第一次开机 …

案例-02.部门管理-查询

一.查询部门-需求 二.查询部门-思路 API接口文档 三.代码实现 1.controller层:负责与前端进行交互,接收前端所发来的请求 注:Slf4j用于记录日志使用,可以省略private static Logger log LoggerFactory.getLogger(DeptControlle…

小程序包体积优化指南:静态资源条件编译与分包编译技巧

在开发小程序时,可能大家都遇到过包体积超限的情况,这对多平台支持、用户体验和加载速度带来不少困扰。UniApp 提供了一些强大的功能,比如静态资源的条件编译和分包编译,这些功能可以帮助我们减少小程序的包体积,提高加…

12. QT控件:多元素控件

0. 概述 Qt中提供的多元素控件 QListWidget QListView QTableWidget QTableView QTreeWidget QTreeView xxWidget 和 xxView的区别 以QTableWidget 和 QTableView 为例: QTableView 是基于MVC设计的控件,QTableView自身不持有数据。使用QTableView需…

CAS单点登录(第7版)20.用户界面

如有疑问,请看视频:CAS单点登录(第7版) 用户界面 概述 概述 对 CAS 用户界面 (UI) 进行品牌化涉及编辑 CSS 样式表以及一小部分相对简单的 HTML 包含文件,也称为视图。(可选&…

android 的抓包工具

charles 抓包工具 官网地址 nullCharles Web Debugging Proxy - Official Sitehttps://www.charlesproxy.com/使用手册一定记得看官网 SSL Certificates • Charles Web Debugging Proxy http请求: 1.启动代理: 2.设置设备端口 3.手机连接当前代理 …

关于视频去水印的一点尝试

一. 视频去水印的几种方法 1. 使用ffmpeg delogo滤镜 delogo 滤镜的原理是通过插值算法,用水印周围的像素填充水印的位置。 示例: ffmpeg -i input.mp4 -filter_complex "[0:v]delogox420:y920:w1070:h60" output.mp4 该命令表示通过滤镜…

预测技术在美团弹性伸缩场景的探索与应用

管理企业大规模服务的弹性伸缩场景中,往往会面临着两个挑战:第一个挑战是精准的负载预测,由于应用实例的启动需要一定预热时间,被动响应式伸缩会在一段时间内影响服务质量;第二个挑战是高效的资源分配,即在…

【含开题报告+文档+PPT+源码】基于Spring+Vue的拾光印记婚纱影楼管理系统

开题报告 本论文旨在探讨基于Spring和Vue框架的拾光印记婚纱影楼管理系统的设计与实现。该系统集成了用户注册登录、个人资料修改、婚庆资讯浏览、婚庆套餐查看、婚纱拍摄预约、婚纱浏览与租赁、客片查看以及在线客服等多项功能,为用户提供了一站式的婚纱影楼服务体…

ASP.NET Core 使用 FileStream 将 FileResult 文件发送到浏览器后删除该文件

FileStream 在向浏览器发送文件时节省了服务器内存和资源,但如果需要删除文件怎么办?本文介绍如何在发送文件后删除文件;用 C# 编写。 另请参阅:位图创建和下载 使用FileStream向浏览器发送数据效率更高,因为文件是从…

字节跳动后端二面

📍1. 数据库的事务性质,InnoDB是如何实现的? 数据库事务具有ACID特性,即原子性、一致性、隔离性和持久性。InnoDB通过以下机制实现这些特性: 🚀 实现细节: 原子性:通过undo log实…

【个人开发】cuda12.6安装vllm安装实践【内含踩坑经验】

1. 背景 vLLM是一个快速且易于使用的LLM推理和服务库。企业级应用比较普遍,尝试安装相关环境,尝试使用。 2. 环境 模块版本python3.10CUDA12.6torch2.5.1xformers0.0.28.post3flash_attn2.7.4vllm0.6.4.post1 2.1 安装flash_attn 具体选择什么版本&…

19.4.9 数据库方式操作Excel

版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。 本节所说的操作Excel操作是讲如何把Excel作为数据库来操作。 通过COM来操作Excel操作,请参看第21.2节 在第19.3.4节【…

2024-2025年主流的开源向量数据库推荐

以下是2024-2025年主流的开源向量数据库推荐,涵盖其核心功能和应用场景: 1. Milvus 特点:专为大规模向量搜索设计,支持万亿级向量数据集的毫秒级搜索,适用于图像搜索、聊天机器人、化学结构搜索等场景。采用无状态架…

vue项目使用vite和vue-router实现history路由模式空白页以及404问题

开发项目的时候,我们一般都会使用路由,但是使用hash路由还是history路由成为了两种选择,因为hash路由在url中带有#号,history没有带#号,看起来更加自然美观。但是hash速度更快而且更通用,history需要配置很…

AI编程01-生成前/后端接口对表-豆包(或Deepseek+WPS的AI

前言: 做过全栈的工程师知道,如果一个APP的项目分别是前端/后端两个团队开发的话,那么原型设计之后,通过接口文档进行开发对接是非常必要的。 传统的方法是,大家一起定义一个接口文档,然后,前端和后端的工程师进行为何,现在AI的时代,是不是通过AI能协助呢,显然可以…

切换git仓库远程地址

1、首先可以先查看一下当前git库的远程地址 【cd .git】 切换到git目录【cat config】查看【cd ../】 返回项目目录 2、 切换到目标远程git地址 【git remote rm origin】 删除现有远程仓库 【git remote add origin url】添加新远程仓库 【cat .git/config】验证是否切换成功…

mapbox 从入门到精通 - 目录

👨‍⚕️ 主页: gis分享者 👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕️ 收录于专栏:mapbox 从入门到精通 文章目录 一、🍀总目录1.1 ☘️ mapbox基础1.2 ☘️…

前端包管理器的发展以及Npm、Yarn和Pnpm对比

在现代前端开发中,包管理器是不可或缺的核心工具。随着 JavaScript 生态的快速发展,开发者经历了从 npm 一统天下到 Yarn 挑战格局,再到 pnpm 创新突破的技术演进。这里将对三种主流包管理器(npm/Yarn/pnpm)进行全方位…