跟着 8.6k Star 的开源数据库,搞 RAG!

news/2024/12/26 9:08:18/文章来源:https://www.cnblogs.com/xueweihan/p/18629166

过去 9 年里,HelloGitHub 月刊累计收录了 3000 多个开源项目。然而,随着项目数量的增加,不少用户反馈:“搜索功能不好用,找不到想要的项目!” 这让我意识到,仅仅收录项目是不够的,还需要通过更智能的方式,帮助用户找到心仪的开源项目。于是,我开始探索如何通过 RAG 技术解决这个问题

检索增强生成(RAG),是赋予生成式人工智能模型信息检索能力的技术。

RAG 技术我早有耳闻,但却一直不知道该从哪里入手。虽然现在有不少容易上手的 RAG 低代码平台,但我不想只停留在“会用”的层面,更希望了解它的实现细节,否则不敢在生产环境中用。不过,要让我直接用 LangChain 和 Ollama 从零搭建一个 RAG 系统,还真有点心里没底。

还好最近 OceanBase 搞事情,在 4.3.3 版本里支持了向量检索功能,更贴心的是,还专门为像我这样对 RAG 感兴趣的新手,准备了一个用 Python 搭建 RAG 聊天机器人的实战教程。

GitHub 地址:github.com/oceanbase/oceanbase

光看永远只是纸上谈兵,所以我干脆上手把玩了一番。

接下来,我将分享如何基于该项目,打造一款 HelloGitHub 开源社区的聊天机器人,内容包括实现过程、细节优化,以及对 RAG 技术的理解与未来展望。

一、介绍

OceanBase 开源的 RAG 聊天机器人,能够通过自然对话更精准地回答与 OceanBase 文档相关的问题。

该项目是基于 langchain、langchain-oceanbase 和 streamlit 构建,处理流程是先将 OceanBase 数据库的文档,通过 Embedding 模型转化为向量数据,并存储在 OceanBase 数据库中。当用户提问时,系统会用相同的模型将问题转化为向量,然后通过向量检索找到相关的文档内容,再将这些文档作为上下文提交给大语言模型,从而生成更精准的回答。

在线体验:oceanbase.com/obi

体验后,我感觉效果还不错,于是就萌生了一个想法:能不能把 OceanBase 的文档,换成 HelloGitHub 月刊的 Markdown 文件,灌进系统里,这样不就摇身一变,成为 HelloGitHub 专属的聊天机器人了吗? 说干就干!

二、安装运行

在开始改造之前,首先需要把项目跑起来。安装运行的步骤在 OceanBase 提供的实战教程中已经很详细了,这里不再过多介绍。运行步骤如下:

  1. 执行 embed_docs.py 脚本,将文档内容向量化后存储到 OB
  2. 启动项目 streamlit run --server.runOnSave false chat_ui.py

启动成功将自动跳转至此界面:

建议

  1. Python 版本管理:运行需要 Python 3.9+,建议使用 pyenv 管理项目的 Python 版本。
  2. 查看数据库:不论是通过 Docker 部署 OceanBase 还是使用 OB Cloud,都建议在本地通过 GUI 工具查看数据库,有助于开发和调试。

运行 embed_docs.py 脚本后,查看数据库中的表,你会发现这些字段:

  • document:存储原始的文档内容
  • embedding:存储文档向量化后的数据
  • metadata:记录文档的名称、路径以及切分后的标题等信息

其中 embedding 列是一个类似数组形式的数据,这个就是通过 Embedding 模型将文档片段转化为向量数据的结果。这些向量数据能够捕捉文本的语义信息,使计算机能够更好地理解文本的含义,从而实现类似语义搜索的功能(计算距离),为后续问题与文档内容的匹配提供基础。

三、动手改造

这个项目除了支持 LLMs API,还可以切换为本地的 Ollama API 使用,只需修改 .env 配置文件即可完成调整:

# 使用支持 embed API 的模型
OLLAMA_URL=localhost:11434/api/embed
OLLAMA_TOKEN=
OLLAMA_MODEL=all-minilm

注意:在调用第三方付费 API 时,一定要注意使用量,建议仅导入部分文档用于测试,或用本地 LLM 调试逻辑,避免不必要的花费。

3.1 导入 HelloGitHub 月刊

通过 embed_docs.py 脚本,将 HelloGitHub 月刊内容向量化并导入到 OceanBase 数据库,命令如下:

python embed_docs.py --doc_base /HelloGitHub/content --table_name hg

参数说明:

  • doc_base:HelloGitHub 内容目录
  • table_name:脚本会自动创建该表,并将数据存储到表中。

但是运行后,我查看数据库时发现 document 字段中包含了许多无意义的内容,例如格式符号或无关信息:

面对这些噪声数据,我编写了一个脚本,清洗 HelloGitHub 月刊文件中无关的格式符号和冗余内容,并重新导入数据库。

3.2 启动服务

在启动服务时,需要通过环境变量 TABLE_NAME 指定要使用的表。命令如下:

TABLE_NAME=hg2 streamlit run --server.runOnSave false chat_ui.py

我试了一下,回答的效果并不理想:

经过测试,我分析问答效果欠佳的原因,可能包括以下几点:

  1. 向量化效果:所选用的模型 all-minilm 仅有 384 维度,可以尝试更大的 Embedding 模型;
  2. 数据清理:虽然清理了一部分无用内容,但可能还有一些噪声数据未处理完全;
  3. 文档完整性:HelloGitHub 的内容结构是否适合问答模型需要进一步分析;
  4. 提示词:需要完善提示词设计,补充更多上下文;

四、优化问答效果

我开始对 RAG 有些感觉了,所以准备切换到付费但效果更好的通义千问 text-embedding-v3 模型(1024 维度),进行调试。

4.1 数据优化

为提升问答效果,我决定进一步优化 document 的构造方式。具体思路是:将 HelloGitHub 网站中的表导入至 OceanBase 数据库,并基于这些表的数据,构建更干净和精准的内容。这样可以最大程度地确保项目数据的全面性,同时减少无关内容的干扰,提升向量检索相关性。

导入表到 OceanBase

OceanBase 和 MySQL 高度兼容,因此,我直接用 Navicat 将 HelloGitHub 的数据表结构和内容,从 MySQL 无缝迁移到了 OceanBase。然后我写了一个 embed_sql.py 脚本,通过直接查询相关表的数据,进而生成更精简的内容(document),同时补充元数据(metadata),并存储到数据库。核心代码如下:

# 构建内容(document)
content = f"""{row.get('name', '未知')}:{row.get('title', '未知标题')}。{row.get('summary', '暂无概要')}"""# 构建元数据(metadata)
metadata = {"repository_name": row.get("name", "N/A"),  # 仓库名称"repository_url": row.get("url", "N/A"),  # 仓库链接"description": row.get("summary", "N/A"),  # 项目描述"category_name": row.get("category_name", "N/A"),  # 类别名称"language": row.get("primary_lang", "N/A"),  # 主要编程语言"chunk_title": row.get("name", "N/A"), "enhanced_title": f'内容 -> {row.get("category_name", "N/A")} -> {row.get("name", "N/A")}'...
}# 将内容和元数据添加到文档对象
docs.append(Document(page_content=content.strip(), metadata=metadata))
# 存储到数据库
vs.add_documents(docs,ids=[str(uuid.uuid4()) for _ in range(len(docs))],
)

经过多轮调试和对比,我发现 document 数据越精简,向量检索效果越好,随后将完整的数据集存入 OceanBase 数据库的 hg5 表。

python embed_sql.py --table_name hg5 --limit=4000              
args Namespace(table_name='hg5', batch_size=4, limit=4000, echo=False)
Using RemoteOpenAI
Processing: 100%|███████████████████████████████████████████████████████████████████████▉| 3356/3357 [09:33<00:00,  5.85row/s]

至此,基于数据库表构造的 document 数据,已经非常干净了。

4.2 提示词优化

在优化完数据后,我开始思考如何优化提示词,并对 LLM 的回答进行引导和强化。以下是针对 LLM 提示词优化的方向:

  1. 明确背景和任务:在提示词中设定问答的背景并限制问题的范围,例如,确保问题只涉及开源项目或 HelloGitHub 的内容。
  2. 丰富上下文:将 metadata(元数据) 和 document(项目描述)同时提供给大模型,让 LLM 有更多上下文来生成精确回答。
  3. 高质量示例:提供高质量的回答示例,统一输出格式。
  4. 约束逻辑:明确要求 LLM 不得虚构答案。如无法回答问题,需清楚指出知识盲点,并合理提供方向性建议。

4.3 处理流程优化

在优化向量检索和回答的流程方面,我做了以下改进:

  1. 扩大检索范围:向量检索默认只返回前 10 条最高相似度的内容。我将其扩展至 20 条,为 LLM 提供更多上下文选择。
  2. 判断相关性:使用提示词指导 LLM 在输出答案前,先判断问题是否与 HelloGitHub 或开源项目相关,避免生成无关回答。
  3. 提炼回答:基于用户输入分析意图后,选出最相关的 5 个项目,并结合元数据生成更贴合用户需求的回答。

4.4 效果展示

除了上面的优化,我还进一步简化了页面、删除用不到的代码,最终呈现效果如下:

回答效果对比:

通过切换至通义千问 text-embedding-v3 模型,同时优化数据、提示词策略和问答流程,让这套 RAG 系统的回答质量有了明显提升,我打算自己盘一盘再上线。所以先放出源码,感兴趣的小伙伴可以作为参考:

GitHub 地址:github.com/521xueweihan/ai-workshop-2024

五、最后

在构建 HelloGitHub 的 RAG 聊天机器人过程中,回答效果一直不好,让我一度产生了放弃的念头。但当我通过查询表里的数据构造 document,并使用维度更大的 Embeding 模型后,回答效果直线提升,才让我重新看到了希望。

这段经历也让我开始认真思考:优化 RAG 的关键是什么?我的答案是 数据+检索。如今,许多企业希望借助 AI 技术赋能已有服务,RAG 则是一种门槛较低的通用解决方案。在这一过程中,数据质量决定了基础,高质量数据往往是从海量数据提纯而来。检索则是确保内容能够被快速且准确提取的关键。否则不管提示词再怎么优化,也无法检索到有价值的内容,就无法实现增强的效果。

另外,我认为在未来的 RAG 应用中,除了向量数据,数据库还需要具备一些关键能力来确保检索和生成的高效性。例如,支持关系型数据和向量数据的混合搜索,不仅能处理结构化和非结构化数据,还能有效减少 RAG 模型中的“幻觉”问题,从而让生成的答案更准确、更有根据。图搜索(知识图谱)同样很重要,它为 RAG 提供复杂推理所需的背景信息,提升生成质量。此外,RAG 应用在许多场景中需要频繁更新和同步数据,因此数据库还需支持实时查询、低延迟响应、事务处理和高可用性,这些是确保 RAG 高效运行的基础。

OceanBase 的分布式架构优势,让它在面对海量数据时依然游刃有余。而新引入的向量存储和检索能力,使得我们能够通过 SQL 轻松获取最“干净”的数据,并在同一个数据库内完成向量化操作。OceanBase 未来可期!

GitHub 地址:github.com/oceanbase/oceanbase

虽然 RAG 技术目前还不像 Web 开发那么成熟,但作为一个潜力巨大的技术方向,值得我们持续关注和学习。作为一名刚刚踏上 RAG 探索之旅的小白,我还有很多需要学习的地方。如果你也对 RAG 充满兴趣,欢迎结伴而行、共同成长!

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【内网】内网远程桌面密码获取

一、远程桌面历史IP获取 1.1 mstsc查看历史登录IP 1.2 注册表地址获取历史登录IP地址 1.3 ListRDPConnections 二、获取 RDP 远程桌面连接凭据 2.1 在凭据管理器中查看 Windows 凭据 2.2 使用 Mimikatz 导出远程桌面连接凭据 2.3 从 svchost 中获取 RDP 连…

直击心灵:别让‘在吗’成为沟通障碍

在聊天过程中,我特别反感收到“在吗”的询问或是“微笑”表情。 当需要请求他人协助时,相较于冷冰冰又显敷衍的“在吗?”或是让人感觉虚伪的“微笑”表情,我更倾向于在“在吗”前加上对方的名字或昵称,随后直接切入主题。这样的沟通方式更为亲切且高效,也更容易得到对方的…

【半解决】开启代理后无法连接github仓库,开启tun模式后无法连接github仓库

背景 如图所示。问题 无法连接github仓库,代理可以正常访问外网。 PS C:\Users\acer\bin\ps> ssh -Tv git@github.com OpenSSH_for_Windows_8.1p1, LibreSSL 3.0.2 debug1: Reading configuration data C:\\Users\\acer/.ssh/config debug1: C:\\Users\\acer/.ssh/config l…

[密码管理/信息安全] 密码管理工具:KeePass vs LastPass vs 1Password [转]

序在互联网上冲浪的时候,遇到个有趣好玩的网站,想看里面内容的时候,往往就会要你注册登录。 这时候就会很崩溃,不注册的话没办法看里面的内容 注册的话,担心收到垃圾邮件,个人信息泄露,注册得不偿失(为了看一篇文章而注册一个账号) 我知道身边的一些人就是很多账号,密…

利用Spring Cloud Gateway Predicate优化微服务路由策略

Spring Cloud Gateway 的路由配置中,predicates(断言)用于定义哪些请求应该匹配特定的路由规则。断言是Gateway在进行路由时,根据具体的请求信息如请求路径、请求方法、请求参数等进行匹配的规则。当一个请求的信息符合断言设置的条件时,Gateway就会将该请求路由到对应的服…

补环境 记录

目前补全 小红书 搞定 抖音 搞定 腾讯滑块 腾讯 位数一样 没时间插桩 周末搞定 对一下 瑞数vmp 阿里 滑块 (目标) 以小肩膀 课程补环境框架为基础 结合了v_tools 插件 ,目前在结合各大补环境框架 优点 搞定了 dom 增删改查 目前 难点 -> innerHTML 实现实现了 当前 元素…

Visual Studio - API调试与测试工具之HTTP文件

VisualStudio2022支持类似RESTClient功能,可通过.http文件便捷调试Api接口,包括创建方式、语法、注释变量、环境文件及身份验证等,功能待完善,测试代码已上传至代码库。后端开发,我们对于Api接口调试测试大致有以下方法:单元测试、Swagger、Postman。 但是每种方式也都有…

tasklet

数据结构初始化tasklet_scheduletasklet_action {{uploading-image-512152.png(uploading...)}}

pelt

为什么需要PELT? 之前CFS以每个运行队列为单位跟踪负载;存在几个问题:一个运行队列存在很多个调度实体,所以无法存在当前的负载来源; 即使工作负载相对稳定的情况下,在rq级别跟踪负载,其值也会产生很大变化。(为什么?)为了解决以上问题:提出了PETL算法,PELT算法跟踪…

fork

dup_task_structsched_forkcopy_mmcopy_thread_tls

page_fault

预备处理do_page_faultdo_anonymous_pagedo_faultdo_wp_page