【RAG】基于向量检索的 RAG (BGE示例)
RAG机器人 结构体
-
文本向量化: 使用 BGE 模型将文档和查询编码为向量。
(BGE 是专为检索任务优化的开源 Embedding 模型,除了本文API调用,也可以通过Hugging Face 本地部署BGE 开源模型) -
向量检索: 从数据库中找到与查询相关的文档片段。
-
答案生成: 结合检索结果和用户输入,调用文心模型生成最终回答。
class RAG_Bot:def __init__(self, vector_db, llm_api, n_results=2):self.vector_db = vector_dbself.llm_api = llm_apiself.n_results = n_resultsdef chat(self, user_query):# 1. 检索search_results = self.vector_db.search(user_query, self.n_results)# 2. 构建 Promptprompt = build_prompt(prompt_template, context=search_results['documents'][0], query=user_query)# 3. 调用 LLMresponse = 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)#####
llama 2有7B, 13B和70B参数。
MyVectorDBConnector:
自定义向量数据库,存储文档向量。
embedding_fn=get_embeddings_bge: 使用 BGE 模型生成向量。
add_documents(paragraphs): 向数据库中添加文档(已提前定义 paragraphs)。
RAG_Bot:
检索增强生成机器人,结合向量搜索与大模型生成。
chat(user_query): 执行“检索→生成”流程:
将用户查询向量化。
从数据库检索相关文档。
将检索结果作为上下文,调用文心模型生成回答。
使用国产模型
import json
import requests
import os# 通过鉴权接口获取 access tokendef get_access_token():"""使用 AK,SK 生成鉴权签名(Access Token):return: access_token,或是None(如果错误)"""url = "https://aip.baidubce.com/oauth/2.0/token"params = {"grant_type": "client_credentials","client_id": os.getenv('ERNIE_CLIENT_ID'),"client_secret": os.getenv('ERNIE_CLIENT_SECRET')}return str(requests.post(url, params=params).json().get("access_token"))# 调用文心千帆 调用 BGE Embedding 接口def get_embeddings_bge(prompts):url = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/embeddings/bge_large_en?access_token=" + get_access_token()payload = json.dumps({"input": prompts})headers = {'Content-Type': 'application/json'}response = requests.request("POST", url, headers=headers, data=payload).json()data = response["data"]return [x["embedding"] for x in data]# 调用文心4.0对话接口
def get_completion_ernie(prompt):url = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions_pro?access_token=" + get_access_token()payload = json.dumps({"messages": [{"role": "user","content": prompt}]})headers = {'Content-Type': 'application/json'}response = requests.request("POST", url, headers=headers, data=payload).json()return response["result"]# 创建一个向量数据库对象
new_vector_db = MyVectorDBConnector("demo_ernie",embedding_fn=get_embeddings_bge
)
# 向向量数据库中添加文档
new_vector_db.add_documents(paragraphs)# 创建一个RAG机器人
new_bot = RAG_Bot(new_vector_db,llm_api=get_completion_ernie
)user_query = "how many parameters does llama 2 have?"response = new_bot.chat(user_query)print(response)
拓展实践
1. 优化 Access Token 管理
- 缓存 Token:减少鉴权接口调用次数,仅在 Token 过期时刷新。
- 示例代码:
from datetime import datetime, timedeltaclass TokenManager:_token = None_expires_at = None@classmethoddef get_token(cls):if cls._token is None or datetime.now() > cls._expires_at:cls._refresh_token()return cls._token@classmethoddef _refresh_token(cls):url = "https://aip.baidubce.com/oauth/2.0/token"params = {"grant_type": "client_credentials","client_id": os.getenv('ERNIE_CLIENT_ID'),"client_secret": os.getenv('ERNIE_CLIENT_SECRET')}response = requests.post(url, params=params)response.raise_for_status()data = response.json()cls._token = data["access_token"]# 默认 Token 有效期为 30 天,但建议按实际返回的 expires_in 设置cls._expires_at = datetime.now() + timedelta(seconds=data.get("expires_in", 2592000) - 300) # 提前 5 分钟刷新
2. 增强错误处理与重试
- 重试网络请求:使用
tenacity
库自动重试失败请求。 - 捕获异常:明确处理常见错误(如网络超时、无效响应)。
- 示例代码:
from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type import requests.exceptions as req_exceptions@retry(stop=stop_after_attempt(3),wait=wait_exponential(multiplier=1, min=2, max=10),retry=retry_if_exception_type((req_exceptions.Timeout, req_exceptions.ConnectionError)) ) def safe_api_request(url, headers, payload):try:response = requests.post(url, headers=headers, data=payload, timeout=10)response.raise_for_status()return response.json()except req_exceptions.HTTPError as e:if response.status_code == 401:TokenManager._refresh_token() # Token 可能过期,强制刷新raiseraise ValueError(f"API 错误: {e.response.text}")
3. 验证环境变量
- 启动时检查:确保关键配置已正确设置。
- 示例代码:
def validate_env_vars():required_vars = ['ERNIE_CLIENT_ID', 'ERNIE_CLIENT_SECRET']missing_vars = [var for var in required_vars if not os.getenv(var)]if missing_vars:raise EnvironmentError(f"缺少环境变量: {', '.join(missing_vars)}")# 在程序初始化时调用 validate_env_vars()
4. 优化向量数据库交互
- 批量插入文档:减少 API 调用次数。
- 分块策略:根据 Embedding 模型的最大输入长度分块文本。
- 示例优化(假设使用
MyVectorDBConnector
):class MyVectorDBConnector:def __init__(self, name, embedding_fn, chunk_size=512):self.embedding_fn = embedding_fnself.chunk_size = chunk_size # 根据模型支持的最大长度设置def add_documents(self, documents):chunks = self._chunk_documents(documents)embeddings = self.embedding_fn(chunks)# 批量存储到向量数据库def _chunk_documents(self, documents):# 实现基于句子或固定长度的分块逻辑pass
优化后的代码示例
整合上述改进后的核心逻辑:
import os
import json
import logging
from datetime import datetime, timedelta
import requests
from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type
import requests.exceptions as req_exceptions# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)# 环境变量校验
def validate_env_vars():required_vars = ['ERNIE_CLIENT_ID', 'ERNIE_CLIENT_SECRET']missing_vars = [var for var in required_vars if not os.getenv(var)]if missing_vars:raise EnvironmentError(f"Missing env vars: {', '.join(missing_vars)}")
validate_env_vars()# Token 管理
class TokenManager:_token = None_expires_at = None@classmethoddef get_token(cls):if cls._token is None or datetime.now() > cls._expires_at:cls._refresh_token()return cls._token@classmethoddef _refresh_token(cls):logger.info("Refreshing access token...")url = "https://aip.baidubce.com/oauth/2.0/token"params = {"grant_type": "client_credentials","client_id": os.getenv('ERNIE_CLIENT_ID'),"client_secret": os.getenv('ERNIE_CLIENT_SECRET')}response = requests.post(url, params=params)response.raise_for_status()data = response.json()cls._token = data["access_token"]cls._expires_at = datetime.now() + timedelta(seconds=data.get("expires_in", 2592000) - 300)# 安全 API 请求
@retry(stop=stop_after_attempt(3),wait=wait_exponential(multiplier=1, min=2, max=10),retry=retry_if_exception_type((req_exceptions.Timeout, req_exceptions.ConnectionError))
)
def safe_api_request(url, headers, payload):try:response = requests.post(url, headers=headers, data=payload, timeout=10)response.raise_for_status()return response.json()except req_exceptions.HTTPError as e:if response.status_code == 401:TokenManager._refresh_token()raiselogger.error(f"API Error: {e.response.text}")raise# 公共 API 调用封装
def call_ernie_api(endpoint, payload):base_url = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop"url = f"{base_url}/{endpoint}?access_token={TokenManager.get_token()}"headers = {'Content-Type': 'application/json'}return safe_api_request(url, headers, json.dumps(payload))# Embedding 接口
def get_embeddings_bge(prompts):logger.info(f"Generating embeddings for {len(prompts)} prompts")response = call_ernie_api("embeddings/bge_large_en", {"input": prompts})return [x["embedding"] for x in response["data"]]# 文心 4.0 对话接口
def get_completion_ernie(prompt):logger.info(f"Generating completion for prompt: {prompt[:50]}...")response = call_ernie_api("chat/completions_pro", {"messages": [{"role": "user", "content": prompt}]})return response["result"]
相关文章:

【RAG】基于向量检索的 RAG (BGE示例)
RAG机器人 结构体 文本向量化: 使用 BGE 模型将文档和查询编码为向量。 (BGE 是专为检索任务优化的开源 Embedding 模型,除了本文API调用,也可以通过Hugging Face 本地部署BGE 开源模型) 向量检索: 从数据库中找到与查询相关的文…...

Vue源码解析之mustache模板引擎
个人简介 👀个人主页: 前端杂货铺 🙋♂️学习方向: 主攻前端方向,正逐渐往全干发展 📃个人状态: 研发工程师,现效力于中国工业软件事业 🚀人生格言: 积跬步…...

python: DDD using postgeSQL and SQL Server
postgreSQL 注意: # psycopg 2 驱动的连接字符串 #engine create_engine(postgresql://post:geovindulocalhost:5433/TechnologyGame) #Session sessionmaker(bindengine)# 使用 psycopg3 驱动的连接字符串 #engine create_engine(postgresqlpsycopg://user:g…...

Python实例:PyMuPDF实现PDF翻译,英文翻译为中文,并按段落创建中文PDF
基于PyMuPDF与百度翻译的PDF翻译处理系统开发:中文乱码解决方案与自动化排版实践 一 、功能预览:将英文翻译为中文后创建的PDF 二、完整代码 from reportlab.lib.pagesizes import letter from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle...

IntelliJ IDEA 2021版创建springboot项目的五种方式
第一种方式,通过https://start.spring.io作为spring Initializr的url来创建项目。 第二种方式,通过https://start.spring.io官网来直接创建springboot项目压缩包,然后导入至我们的idea中。 点击generate后,即可生成压缩包…...

c#面试题整理6
1.String类能否被继承,为什么 可以看到String类的修饰符是sealed,即是密封类,故不可被继承 2.一个对象的方法是否只能由一个线程访问 不是,但是可通过同步机制,确保同一个时间只有一个线程访问 3.计算2*8ÿ…...

跟着 Lua 5.1 官方参考文档学习 Lua (12)
文章目录 5.7 – Input and Output Facilities补充内容io.input ([file])io.read ()io.write ()io.output ([file])io.lines ([filename])io.flush ()io.close ([file])io.open (filename [, mode])io.popen (prog [, mode])io.tmpfile ()io.type (ob)file:read ()file:lines (…...

大语言模型中的归一化技术:LayerNorm与RMSNorm的深入研究
在LLama等大规模Transformer架构的语言模型中,归一化模块是构建网络稳定性的关键组件。本文将系统分析归一化技术的必要性,并详细阐述为何原始Transformer架构中的LayerNorm在LLama模型中被RMSNorm所替代的技术原理。 归一化技术的基础原理 归一化的核…...

nodejs使用WebSocket实现聊天效果
在nodejs中使用WebSocket实现聊天效果(简易实现) 安装 npm i ws 实现 创建 server.js /*** 创建一个 WebSocket 服务器,监听指定端口,并处理客户端连接和消息。** param {Object} WebSocket - 引入的 WebSocket 模块,…...

【仿muduo库one thread one loop式并发服务器实现】
文章目录 一、项目介绍1-1、项目总体简介1-2、项目开发环境1-3、项目核心技术1-4、项目开发流程1-5、项目如何使用 二、框架设计2-1、功能模块划分2-1-1、SERVER模块2-1-2、协议模块 2-2、项目蓝图2-2-1、整体图2-2-2、模块关系图2-2-2-1、Connection 模块关系图2-2-2-2、Accep…...

10.2 继承与多态
文章目录 继承多态 继承 继承的作用是代码复用。派生类自动获得基类的除私有成员外的一切。基类描述一般特性,派生类提供更丰富的属性和行为。在构造派生类时,其基类构造函数先被调用,然后是派生类构造函数。在析构时顺序刚好相反。 // 基类…...

Go红队开发—格式导出
文章目录 输出功能CSV输出CSV 转 结构体结构体 转 CSV端口扫描结果使用CSV格式导出 HTML输出Sqlite输出nmap扫描 JSONmap转json结构体转jsonjson写入文件json编解码json转结构体json转mapjson转string练习:nmap扫描结果导出json格式 输出功能 在我们使用安全工具的…...

线性代数之矩阵特征值与特征向量的数值求解方法
文章目录 前言1. 幂迭代法(Power Iteration)幂法与反幂法求解矩阵特征值幂法求最大特征值编程实现补充说明 2. 逆幂迭代法(Inverse Iteration)移位反幂法 3. QR 算法(QR Algorithm)——稠密矩阵理论推导编程…...

Spring MVC源码分析のinit流程
文章目录 前言一、 init1.1、createWebApplicationContext1.2、onRefresh 二、请求处理器2.1、RequestMapping2.2、Controller接口2.3、HttpRequestHandler接口2.4、HandlerFunction 三、initHandlerMappings3.1、getDefaultStrategies3.1.1、RequestMappingHandlerMapping3.1.…...

【后端开发】go-zero微服务框架实践(goland框架对比,go-zero开发实践,文件上传问题优化等等)
【后端开发】go-zero微服务框架实践(goland框架对比,go-zero开发实践,文件上传问题优化等) 文章目录 1、go框架对比介绍2、go-zero 微服务开发实践3、go-zero 文件上传问题优化 1、go框架对比介绍 国内开源goland框架对比 1 go-…...

C#程序加密与解密Demo程序示例
目录 一、加密程序功能介绍 1、加密用途 2、功能 3、程序说明 4、加密过程 5、授权的注册文件保存方式 二、加密程序使用步骤 1、步骤一 编辑2、步骤二 3、步骤三 4、步骤四 三、核心代码说明 1、获取电脑CPU 信息 2、获取硬盘卷标号 3、机器码生成 3、 生成…...

小程序事件系统 —— 33 事件传参 - data-*自定义数据
事件传参:在触发事件时,将一些数据作为参数传递给事件处理函数的过程,就是事件传参; 在微信小程序中,我们经常会在组件上添加一些自定义数据,然后在事件处理函数中获取这些自定义数据,从而完成…...

深入解析 JavaScript 原型与原型链:从原理到应用
原型和原型链是 JavaScript 中实现对象继承和属性查找的核心机制。为了更深入地理解它们,我们需要从底层原理、实现机制以及实际应用等多个角度进行分析。 1. 原型(Prototype) 1.1 什么是原型? 每个 JavaScript 对象(…...

关于AI数据分析可行性的初步评估
一、结论:可在部分环节嵌入,无法直接处理大量数据 1.非本地部署的AI应用处理非机密文件没问题,内部文件要注意数据安全风险。 2.AI(指高规格大模型)十分适合探索性研究分析,对复杂报告无法全流程执行&…...

回归预测 | Matlab实现GWO-BP-Adaboost基于灰狼算法优化BP神经网络结合Adaboost思想的回归预测
回归预测 | Matlab实现GWO-BP-Adaboost基于灰狼算法优化BP神经网络结合Adaboost思想的回归预测 目录 回归预测 | Matlab实现GWO-BP-Adaboost基于灰狼算法优化BP神经网络结合Adaboost思想的回归预测回归效果基本介绍GWO-BP-Adaboost:基于灰狼算法优化BP神经网络结合Adaboost思想…...

ARM Cortex-M 内存映射详解:如何基于寄存器直接读写 寄存器映射方式编码程序 直接操作硬件寄存器来控制 MCU
ARM Cortex-M 的系统映射空间 在 STM32 等 ARM Cortex-M 系列 MCU 中,内存地址空间按照 存储功能 进行了严格划分,包括 Flash(程序存储)、RAM(数据存储)、外设寄存器(GPIO、UART、SPI 等&am…...

深度学习实战车辆目标跟踪与计数
本文采用YOLOv8作为核心算法框架,结合PyQt5构建用户界面,使用Python3进行开发。YOLOv8以其高效的实时检测能力,在多个目标检测任务中展现出卓越性能。本研究针对车辆目标数据集进行训练和优化,该数据集包含丰富的车辆目标图像样本…...

django中视图作用和视图功能 以及用法
在 Django REST Framework(DRF)中,视图(View)是处理 HTTP 请求并返回响应的核心组件。DRF 提供了多种视图类,适用于不同的场景和需求。以下是 DRF 中常见的视图类及其作用、使用方法的详细说明: 一、DRF 视图的分类 DRF 的视图可以分为以下几类: 基于函数的视图(Func…...

【每日学点HarmonyOS Next知识】输入框自动获取焦点、JS桥实现方式、Popup设置全屏蒙版、鼠标事件适配、Web跨域
1、HarmonyOS TextInput或TextArea如何自动获取焦点? 可以使用 focusControl.requestFocus 对需要获取焦点的组件设置焦点,具体可以参考文档: https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/ts-universal-attribut…...

【学习思维模型】
学习思维模型 一、理解类模型二、记忆类模型三、解决问题类模型四、结构化学习模型五、效率与习惯类模型六、高阶思维模型七、实践建议八、新增学习思维模型**1. 波利亚问题解决四步法****2. 主动回忆(Active Recall)****3. 鱼骨图(因果图/Ishikawa Diagram)****4. MECE原则…...

MyBatis-Plus分页控件使用及使用过程发现的一个坑
最近维护一个旧项目的时候,出现了一个BUG,经排查后发现是Mybatis-plus分页控件使用的时候需要注意的一个问题,故在本地使用MybatisPlus模拟出现了一下这个问题。 首先,先说一下MyBatis-Plus的使用: 1)引入…...

STM32的APB1和APB2的区别
STM32微控制器中的APB1和APB2的区别 STM32微控制器中的APB1和APB2是两种不同的外设总线,主要区别在于时钟速度、连接的外设以及用途。以下是它们的详细对比: 1. 时钟速度 APB1 (Advanced Peripheral Bus 1): 低速总线,时钟频率通常为系统时钟…...

JS一些小知识点
一、|| 运算符 plain this.ctx.body { type: type || 0, // ||在此处用法用于默认值填充,判断是否传参或该值是否存在,如果不存在就使用||后买你的值作为默认值 code: code || 0, msg: msg || SUCCESS, data: data || {}, ...others }; 二、trim() 方…...

手写Tomcat:实现基本功能
首先,Tomcat是一个软件,所有的项目都能在Tomcat上加载运行,Tomcat最核心的就是Servlet集合,本身就是HashMap。Tomcat需要支持Servlet,所以有servlet底层的资源:HttpServlet抽象类、HttpRequest和HttpRespon…...

C#变量与变量作用域详解
一、变量基础 1. 声明与初始化 声明语法:<数据类型> <变量名>(如 int age; string name)初始化要求: 1、 类或结构体中的字段变量(全局变量)无需显式初始化,默认值…...