Tips
Go
(18条消息) Go语言自学系列 | golang包_COCOgsta的博客-CSDN博客
(18条消息) Go语言自学系列 | golang并发编程之channel的遍历_COCOgsta的博客-CSDN博客
(18条消息) Go语言自学系列 | golang并发编程之select switch_COCOgsta的博客-CSDN博客_golang select switch
(18条消息) Go语言自学系列 | golang并发编程之runtime包_COCOgsta的博客-CSDN博客_golang runtime包
(18条消息) Go语言自学系列 | golang接口值类型接收者和指针类型接收者_COCOgsta的博客-CSDN博客
(18条消息) Go语言自学系列 | golang并发编程之Timer_COCOgsta的博客-CSDN博客
(18条消息) Go语言自学系列 | golang方法_COCOgsta的博客-CSDN博客
(18条消息) Go语言自学系列 | golang并发编程之WaitGroup实现同步_COCOgsta的博客-CSDN博客
(18条消息) Go语言自学系列 | golang构造函数_COCOgsta的博客-CSDN博客_golang 构造函数
(18条消息) Go语言自学系列 | golang方法接收者类型_COCOgsta的博客-CSDN博客_golang 方法接收者
(18条消息) Go语言自学系列 | golang接口_COCOgsta的博客-CSDN博客
(18条消息) Go语言自学系列 | golang接口和类型的关系_COCOgsta的博客-CSDN博客
(18条消息) Go语言自学系列 | golang结构体_COCOgsta的博客-CSDN博客
(18条消息) Go语言自学系列 | golang结构体_COCOgsta的博客-CSDN博客
(18条消息) Go语言自学系列 | golang标准库os模块 - File文件读操作_COCOgsta的博客-CSDN博客_golang os.file
(18条消息) Go语言自学系列 | golang继承_COCOgsta的博客-CSDN博客_golang 继承
(18条消息) Go语言自学系列 | golang嵌套结构体_COCOgsta的博客-CSDN博客_golang 结构体嵌套
(18条消息) Go语言自学系列 | golang并发编程之Mutex互斥锁实现同步_COCOgsta的博客-CSDN博客
(18条消息) Go语言自学系列 | golang并发变成之通道channel_COCOgsta的博客-CSDN博客
(18条消息) Go语言自学系列 | golang并发编程之原子操作详解_COCOgsta的博客-CSDN博客_golang 原子操作
(18条消息) Go语言自学系列 | golang并发编程之原子变量的引入_COCOgsta的博客-CSDN博客_go 原子变量
(18条消息) Go语言自学系列 | golang并发编程之协程_COCOgsta的博客-CSDN博客_golang 协程 并发
(18条消息) Go语言自学系列 | golang接口嵌套_COCOgsta的博客-CSDN博客_golang 接口嵌套
(18条消息) Go语言自学系列 | golang包管理工具go module_COCOgsta的博客-CSDN博客_golang 包管理器
(18条消息) Go语言自学系列 | golang标准库os模块 - File文件写操作_COCOgsta的博客-CSDN博客_go os模块
(18条消息) Go语言自学系列 | golang结构体的初始化_COCOgsta的博客-CSDN博客_golang 结构体初始化
(18条消息) Go语言自学系列 | golang通过接口实现OCP设计原则_COCOgsta的博客-CSDN博客
(18条消息) Go语言自学系列 | golang标准库os包进程相关操作_COCOgsta的博客-CSDN博客_golang os包
(18条消息) Go语言自学系列 | golang标准库ioutil包_COCOgsta的博客-CSDN博客_golang ioutil
(18条消息) Go语言自学系列 | golang标准库os模块 - 文件目录相关_COCOgsta的博客-CSDN博客_go语言os库
Golang技术栈,Golang文章、教程、视频分享!
(18条消息) Go语言自学系列 | golang结构体指针_COCOgsta的博客-CSDN博客_golang 结构体指针
Ansible
太厉害了,终于有人能把Ansible讲的明明白白了,建议收藏_互联网老辛
ansible.cfg配置详解
Docker
Docker部署
linux安装docker和Docker Compose
linux 安装 docker
Docker中安装Docker遇到的问题处理
Docker常用命令
docker常用命令小结
docker 彻底卸载
Docker pull 时报错:Get https://registry-1.docker.io/v2/library/mysql: net/http: TLS handshake timeout
Docker 拉镜像无法访问 registry-x.docker.io 问题(Centos7)
docker 容器内没有权限
Linux中关闭selinux的方法是什么?
docker run 生成 docker-compose
Docker覆盖网络部署
docker pull后台拉取镜像
docker hub
Redis
Redis 集群别乱搭,这才是正确的姿势
linux_离线_redis安装
怎么实现Redis的高可用?(主从、哨兵、集群) - 雨点的名字 - 博客园
redis集群离线安装
always-show-logo yes
Redis集群搭建及原理
[ERR] Node 172.168.63.202:7001 is not empty. Either the nodealready knows other nodes (check with CLUSTER NODES) or contains some - 亲爱的不二999 - 博客园
Redis daemonize介绍
redis 下载地址
Redis的redis.conf配置注释详解(三) - 云+社区 - 腾讯云
Redis的redis.conf配置注释详解(一) - 云+社区 - 腾讯云
Redis的redis.conf配置注释详解(二) - 云+社区 - 腾讯云
Redis的redis.conf配置注释详解(四) - 云+社区 - 腾讯云
Linux
在终端连接ssh的断开关闭退出的方法
漏洞扫描 - 灰信网(软件开发博客聚合)
find 命令的参数详解
vim 编辑器搜索功能
非root安装rpm时,mockbuild does not exist
Using a SSH password instead of a key is not possible because Host Key checking
(9条消息) 安全扫描5353端口mDNS服务漏洞问题_NamiJava的博客-CSDN博客_5353端口
Linux中使用rpm命令安装rpm包
ssh-copy-id非22端口的使用方法
How To Resolve SSH Weak Key Exchange Algorithms on CentOS7 or RHEL7 - infotechys.com
Linux cp 命令
yum 下载全量依赖 rpm 包及离线安装(终极解决方案) - 叨叨软件测试 - 博客园
How To Resolve SSH Weak Key Exchange Algorithms on CentOS7 or RHEL7 - infotechys.com
RPM zlib 下载地址
运维架构网站
欢迎来到 Jinja2
/usr/local/bin/ss-server -uv -c /etc/shadowsocks-libev/config.json -f /var/run/s
ruby 安装Openssl 默认安装位置
Linux 常用命令学习 | 菜鸟教程
linux 重命名文件和文件夹
linux命令快速指南
ipvsadm
Linux 下查找日志中的关键字
Linux 切割大 log 日志
CentOS7 关于网络的设置
rsync 命令_Linux rsync 命令用法详解:远程数据同步工具
linux 可视化界面安装
[问题已处理]-执行yum卡住无响应
GCC/G++升级高版本
ELK
Docker部署ELK
ELK+kafka+filebeat+Prometheus+Grafana - SegmentFault 思否
(9条消息) Elasticsearch设置账号密码_huas_xq的博客-CSDN博客_elasticsearch设置密码
Elasticsearch 7.X 性能优化
Elasticsearch-滚动更新
Elasticsearch 的内存优化_大数据系统
Elasticsearch之yml配置文件
ES 索引为Yellow状态
Logstash:Grok filter 入门
logstash grok 多项匹配
Mysql
Mysql相关Tip
基于ShardingJDBC实现数据库读写分离 - 墨天轮
MySQL-MHA高可用方案
京东三面:我要查询千万级数据量的表,怎么操作?
OpenStack
(16条消息) openstack项目中遇到的各种问题总结 其二(云主机迁移、ceph及扩展分区)_weixin_34104341的博客-CSDN博客
OpenStack组件介绍
百度大佬OpenStack流程
openstack各组件介绍
OpenStack生产实际问题总结(一)
OpenStack Train版离线部署
使用Packstack搭建OpenStack
K8S
K8S部署
K8S 集群部署
kubeadm 重新 init 和 join-pudn.com
Kubernetes 实战总结 - 阿里云 ECS 自建 K8S 集群 Kubernetes 实战总结 - 自定义 Prometheus
【K8S实战系列-清理篇1】k8s docker 删除没用的资源
Flannel Pod Bug汇总
Java
Jdk 部署
JDK部署
java线程池ThreadPoolExecutor类使用详解 - bigfan - 博客园
ShardingJDBC实现多数据库节点分库分表 - 墨天轮
Maven Repository: Search/Browse/Explore
其他
Git在阿里,我们如何管理代码分支?
chrome F12调试网页出现Paused in debugger
体验IntelliJ IDEA的远程开发(Remote Development) - 掘金
Idea远程调试
PDF转MD
强哥分享干货
优秀开源项目集合
vercel 配合Github 搭建项目Doc门户
如何用 Github Issues 写技术博客?
Idea 2021.3 Maven 3.8.1 报错 Blocked mirror for repositories 解决
列出maven依赖
[2022-09 持续更新] 谷歌 google 镜像 / Sci-Hub 可用网址 / Github 镜像可用网址总结
阿里云ECS迁移
linux访问github
一文教你使用 Docker 启动并安装 Nacos-腾讯云开发者社区-腾讯云
Nginx
Nginx 部署
Nginx 部署安装
Nginx反向代理cookie丢失的问题_longzhoufeng的博客-CSDN博客_nginx 代理后cookie丢失
Linux 系统 Https 证书生成与Nginx配置 https
数据仓库
实时数仓
松果出行 x StarRocks:实时数仓新范式的实践之路
实时数据仓库的一些分层和分层需要处理的事情,以及数据流向
湖仓一体电商项目
湖仓一体电商项目(一):项目背景和架构介绍
湖仓一体电商项目(二):项目使用技术及版本和基础环境准备
湖仓一体电商项目(三):3万字带你从头开始搭建12个大数据项目基础组件
数仓笔记
数仓学习总结
数仓常用平台和框架
数仓学习笔记
数仓技术选型
尚硅谷教程
尚硅谷学习笔记
尚硅谷所有已知的课件资料
尚硅谷大数据项目之尚品汇(11数据质量管理V4.0)
尚硅谷大数据项目之尚品汇(10元数据管理AtlasV4.0)
尚硅谷大数据项目之尚品汇(9权限管理RangerV4.0)
尚硅谷大数据项目之尚品汇(8安全环境实战V4.0)
尚硅谷大数据项目之尚品汇(7用户认证KerberosV4.1)
尚硅谷大数据项目之尚品汇(6集群监控ZabbixV4.1)
尚硅谷大数据项目之尚品汇(5即席查询PrestoKylinV4.0)
尚硅谷大数据项目之尚品汇(4可视化报表SupersetV4.0)
尚硅谷大数据项目之尚品汇(3数据仓库系统)V4.2.0
尚硅谷大数据项目之尚品汇(2业务数据采集平台)V4.1.0
尚硅谷大数据项目之尚品汇(1用户行为采集平台)V4.1.0
数仓治理
数据中台 元数据规范
数据中台的那些 “经验与陷阱”
2万字详解数据仓库数据指标数据治理体系建设方法论
数据仓库,为什么需要分层建设和管理? | 人人都是产品经理
网易数帆数据治理演进
数仓技术
一文看懂大数据生态圈完整知识体系
阿里云—升舱 - 数据仓库升级白皮书
最全企业级数仓建设迭代版(4W字建议收藏)
基于Hue,Dolphinscheduler,HIVE分析数据仓库层级实现及项目需求案例实践分析
详解数据仓库分层架构
数据仓库技术细节
大数据平台组件介绍
总览 2016-2021 年全球机器学习、人工智能和大数据行业技术地图
Apache DolphinScheduler 3.0.0 正式版发布!
数据仓库面试题——介绍下数据仓库
数据仓库为什么要分层,各层的作用是什么
Databend v0.8 发布,基于 Rust 开发的现代化云数据仓库 - OSCHINA - 中文开源技术交流社区
数据中台
数据中台设计
大数据同步工具之 FlinkCDC/Canal/Debezium 对比
有数数据开发平台文档
Shell
Linux Shell 命令参数
shell 脚本编程
一篇教会你写 90% 的 Shell 脚本
Kibana
Kibana 查询语言(KQL)
Kibana:在 Kibana 中的四种表格制作方式
Kafka
Kafka部署
canal 动态监控 Mysql,将 binlog 日志解析后,把采集到的数据发送到 Kafka
OpenApi
OpenAPI 标准规范,了解一下?
OpenApi学术论文
贵阳市政府数据开放平台设计与实现
OpenAPI简介
开放平台:运营模式与技术架构研究综述
管理
技术部门Leader是不是一定要技术大牛担任?
华为管理体系流程介绍
DevOps
*Ops
XOps 已经成为一个流行的术语 - 它是什么?
Practical Linux DevOps
Jenkins 2.x实践指南 (翟志军)
Jenkins 2权威指南 ((美)布伦特·莱斯特(Brent Laster)
DevOps组件高可用的思路
KeepAlived
VIP + KEEPALIVED + LVS 遇到Connection Peer的问题的解决
MinIO
MinIO部署
Minio 分布式集群搭建部署
Minio 入门系列【16】Minio 分片上传文件 putObject 接口流程源码分析
MinioAPI 浅入及问题
部署 minio 兼容 aws S3 模式
超详细分布式对象存储 MinIO 实战教程
Hadoop
Hadoop 部署
Hadoop集群部署
windows 搭建 hadoop 环境(解决 HADOOP_HOME and hadoop.home.dir are unset
Hadoop 集群搭建和简单应用(参考下文)
Hadoop 启动 NameNode 报错 ERROR: Cannot set priority of namenode process 2639
jps 命令查看 DataNode 进程不见了 (hadoop3.0 亲测可用)
hadoop 报错: Operation category READ is not supported in state standby
Spark
Spark 部署
Spark 集群部署
spark 心跳超时分析 Cannot receive any reply in 120 seconds
Spark学习笔记
apache spark - Failed to find data source: parquet, when building with sbt assembly
Spark Thrift Server 架构和原理介绍
InLong
InLong 部署
Apache InLong部署文档
安装部署 - Docker 部署 - 《Apache InLong v1.2 中文文档》 - 书栈网 · BookStack
基于 Apache Flink SQL 的 InLong Sort ETL 方案解析
关于 Apache Pulsar 在 Apache InLong 接入数据
zookeeper
zookeeper 部署
使用 Docker 搭建 Zookeeper 集群
美团技术团队
StarRocks
StarRocks技术白皮书(在线版)
JuiceFS
AI 场景存储优化:云知声超算平台基于 JuiceFS 的存储实践
JuiceFS 在 Elasticsearch/ClickHouse 温冷数据存储中的实践
JuiceFS format
元数据备份和恢复 | JuiceFS Document Center
JuiceFS 元数据引擎选型指南
Apache Hudi 使用文件聚类功能 (Clustering) 解决小文件过多的问题
普罗米修斯
k8s 之 Prometheus(普罗米修斯)监控,简单梳理下 K8S 监控流程
k8s 部署 - 使用helm3部署监控prometheus(普罗米修斯),从零到有,一文搞定
k8s 部署 - 使用 helm3 部署监控 prometheus(普罗米修斯),从零到有,一文搞定
k8s 部署 - 如何完善 k8s 中 Prometheus(普罗米修斯)监控项目呢?
k8s 部署 - k8s 中 Prometheus(普罗米修斯)的大屏展示 Grafana + 监控报警
zabbix
一文带你掌握 Zabbix 监控系统
Stream Collectors
Nvidia
Nvidia API
CUDA Nvidia驱动安装
NVIDIA驱动失效简单解决方案:NVIDIA-SMI has failed because it couldn‘t communicate with the NVIDIA driver.
ubuntu 20 CUDA12.1安装流程
nvidia开启持久化模式
nvidia-smi 开启持久化
Harbor
Harbor部署文档
Docker 爆出 it doesn't contain any IP SANs
pandoc
其他知识
大模型
COS 597G (Fall 2022): Understanding Large Language Models
如何优雅的使用各类LLM
ChatGLM3在线搜索功能升级
当ChatGLM3能用搜索引擎时
OCR神器,PDF、数学公式都能转
Stable Diffusion 动画animatediff-cli-prompt-travel
基于ERNIE Bot自定义虚拟数字人生成
pika负面提示词
开通GPT4的方式
GPT4网站
低价开通GPT Plus
大模型应用场景分享
AppAgent AutoGPT变体
机器学习
最大似然估计
权衡偏差(Bias)和方差(Variance)以最小化均方误差(Mean Squared Error, MSE)
伯努利分布
方差计算公式
均值的高斯分布估计
没有免费午餐定理
贝叶斯误差
非参数模型
最近邻回归
表示容量
最优容量
权重衰减
正则化项
Sora
Sora官方提示词
看完32篇论文,你大概就知道Sora如何炼成? |【经纬低调出品】
Sora论文
Sora 物理悖谬的几何解释
Sora 技术栈讨论
RAG垂直落地
DB-GPT与TeleChat-7B搭建相关RAG知识库
ChatWithRTX
ChatRTX安装教程
ChatWithRTX 踩坑记录
ChatWithRTX 使用其他量化模型
ChatWithRTX介绍
RAG 相关资料
英伟达—大模型结合 RAG 构建客服场景自动问答
又一大模型技术开源!有道自研RAG引擎QAnything正式开放下载
收藏!RAG入门参考资料开源大总结:RAG综述、介绍、比较、预处理、RAG Embedding等
RAG调研
解决现代RAG实际生产问题
解决现代 RAG 系统中的生产问题-II
Modular RAG and RAG Flow: Part Ⅰ
Modular RAG and RAG Flow: Part II
先进的Retriever技术来增强你的RAGs
高级RAG — 使用假设文档嵌入 (HyDE) 改进检索
提升 RAG:选择最佳嵌入和 Reranker 模型
LangGraph
增强型RAG:re-rank
LightRAG:使用 PyTorch 为 LLM 应用程序提供支持
RAG 101:分块策略
模型训练
GPU相关资料
[教程] conda安装简明教程(基于miniconda和Windows)
PyTorch CUDA对应版本 | PyTorch
资料
李一舟课程全集
零碎资料
苹果各服共享ID
数据中心网络技术概览
华为大模型训练学习笔记
百度AIGC工程师认证考试答案(可换取工信部证书)
百度智能云生成式AI认证工程师 考试和证书查询指南
深入理解 Megatron-LM(1)基础知识
QAnything
接入QAnything的AI问答知识库,可私有化部署的企业级WIKI知识库
wsl --update失效Error code: Wsl/UpdatePackage/0x80240438的解决办法
Docker Desktop 启动docker engine一直转圈解决方法
win10开启了hyper-v,docker 启动还是报错 docker desktop windows hypervisor is not present
WSL虚拟磁盘过大,ext4迁移 Windows 中创建软链接和硬链接
WSL2切换默认的Linux子系统
Windows的WSL子系统,自动开启sshd服务
新版docker desktop设置wsl(使用windown的子系统)
WSL 开启ssh
Windows安装网易开源QAnything打造智能客服系统
芯片
国内互联网大厂自研芯片梳理
超算平台—算力供应商
Linux 磁盘扩容
Linux使用growpart工具进行磁盘热扩容(非LVM扩容方式)
关于centos7 扩容提示no tools available to resize disk with 'gpt' - o夜雨随风o - 博客园
(小插曲)neo4j配置apoc插件后检查版本发现:Unknown function ‘apoc.version‘ “EXPLAIN RETURN apoc.version()“
vfio-pci与igb_uio映射硬件资源到DPDK的流程分析
KubeVirt
vnc server配置、启动、重启与连接 - 王约翰 - 博客园
虚拟机Bug解决方案
kubevirt 如何通过CDI上传镜像文件
在 K8S 上也能跑 VM!KubeVirt 簡介與建立(部署篇) | Cloud Solutions
KubeVirt 04:容器化数据导入 – 小菜园
Python
安装 flash_attn
手把手教你在linux上安装pytorch与cuda
AI
在启智社区基于PyTorch运行国产算力卡的模型训练实验
Scaling law
免费的GPT3.5 API
AI Engineer Roadmap & Resources 🤖
模型排行
edk2
K8S删除Evicted状态的pod
docker 中启动 docker
远程本地多用户桌面1.17(一种不让电脑跟你抢键鼠的思路) - 哔哩哔哩
华为鲲鹏服务器(ARM架构)部署Prometheus
在Linux上安装配置Grafana_AI开发平台ModelArts_华为云
abrt-ccpp干崩服务器查询记录
kubevirt 中文社区
VNCServer 连接方法
Pod创建流程代码版本[kubelet篇]
[译]深入剖析 Kubernetes MutatingAdmissionWebhook-腾讯云开发者社区-腾讯云
[译]深入剖析 Kubernetes MutatingAdmissionWebhook-腾讯云开发者社区-腾讯云
深入理解 Kubernetes Admission Webhook-阳明的博客
CentOS7 安装 mbedtls和mbedtls-devel
-
+
首页
RAG 101:分块策略
![img](https://yg9538.kmgy.top/20241209170344533.png) 我们如何拆分球?(使用 Cava 生成) T大型语言模型在单个请求中可以处理的最大令牌数称为上下文长度(或上下文窗口)。下表显示了[所有版本的 GPT-4 的上下文长度](https://platform.openai.com/docs/models/gpt-4-turbo-and-gpt-4)(截至 2024 年 9 月)。虽然上下文长度随着每次迭代和每个新模型而增加,但我们能为模型提供的信息仍然存在限制。此外,输入的大小与 LLM 生成的响应的上下文相关性之间存在负相关,简短而集中的输入比包含大量信息的长上下文产生更好的结果。这强调了将数据分解为更小、更相关的块以确保 LLM 做出更适当响应的重要性——至少在 LLM 无需重新训练即可处理大量数据之前。 gpt-4 模型的上下文窗口限制(引用自 [OpenAI](https://platform.openai.com/docs/models/gpt-4-turbo-and-gpt-4)) 图像中表示的上下文窗口**包括输入和输出标记。** # 为什么上下文长度很重要 虽然较长的上下文为模型提供了更全面的画面,并帮助它理解关系并做出更好的推理,但另一方面,较短的上下文减少了模型需要理解的数据量,从而减少了延迟,使模型更具响应性。它还有助于最大限度地减少 LLM 的幻觉,因为仅向模型提供相关数据。因此,这是性能、效率和数据复杂程度之间的平衡,我们需要运行实验,确定多少数据是用合理资源产生最佳结果的合适数据量。 GPT-4 模型的 128k 令牌可能看起来很多,所以让我们将它们转换为实际的单词并正确看待它们。来自 [OpenAI Tokenizer](https://platform.openai.com/tokenizer): > 一个有用的经验法则是,对于常见的英语文本,一个标记通常对应于 ~4 个字符的文本。这大约相当于一个单词的 3/4(所以 100 个标记 ~= 75 个单词) 让我们以 [Arthur Conan Doyle 的 The Hound of the Baskervilles](https://www.gutenberg.org/ebooks/2852)(Project Gutenberg License)为例。这本书长 7734 行,有 62303 个单词,大约有 83,700 个代币 如果您对精确计算代币而不仅仅是近似感兴趣,您可以使用 OpenAI 的 [tiktoken](https://github.com/openai/tiktoken): ``` import request. from tiktoken import encoding_for_model url = "https://www.gutenberg.org/cache/epub/3070/pg3070.txt" response = requests.get(url) if response.status_code == 200: book_full_text = response.text encoder = encoding_for_model("gpt-4o") tokens = encoder.encode(book_full_text) print(f"Number of tokens: {len(tokens)}") ``` 它给出了要为`Number of tokens: 82069` # 什么是分块 ![img](https://yg9538.kmgy.top/20241209170345110.png) 块状奶酪!!(使用 Canva 生成) 我喜欢 wiki 对分块的[定义](https://en.wikipedia.org/wiki/Chunking_(psychology)#:~:text=In cognitive psychology%2C chunking is,whole later on in memory.),因为它适用于 RAG,就像在认知心理学中一样。 > 分块是将一组信息中的一小部分绑定在一起的过程。这些块旨在提高材料的短期保留率,从而绕过工作内存的有限容量,使工作内存更有效 将大型数据集拆分为更小、有意义的信息片段,以便更有效地使用 LLM 的非参数内存的过程称为分块。有许多不同的方法可以拆分数据以改进 RAG 的块检索,我们需要根据正在使用的数据类型进行选择。 分块是 RAG 管道中一个关键的预检索步骤,它直接影响检索过程并显着影响最终输出。在本文中,我们将研究最常见的分块策略,并在数据上下文中评估它们的检索指标。 # 分离器的直觉 与其立即回顾不同库中可用的现有分块策略/拆分器,不如开始构建一个简单的拆分器并探索需要考虑的重要方面,以建立编写新拆分器的直觉。让我们从一个基本的 splitter 开始,然后通过解决它的缺点/限制来逐步改进它。 ## 1. 朴素分块 当我们谈论拆分数据时,我们首先想到的是在换行符处拆分数据。让我们继续实施。但正如你所看到的,它留下了很多回程回车字符。此外,我们只假设*了 \n* 和 *\r*,因为我们只处理英语,但是如果我们想解析其他语言怎么办?让我们添加灵活性,以便也传入要拆分的字符。 ``` def naive_splitter_v2(text: str, separators: List[str] = ["\n", "\r"]) -> List[str]: """Splits text at every separator""" splits = [text] for sep in separators: splits = [segment for part in result for segment in part.split(sep) if segment] return splits ``` ![img](https://yg9538.kmgy.top/20241209170344945.png) naive_splitter_v2 的输出 您可能已经从输出中猜到了为什么我们将此方法称为 Naive。这个想法有很多缺点: 1. 没有 Chunk 限制。只要一行有分隔符之一,它就会中断,但是如果我们一个块没有这些分隔符怎么办,它可以达到任何长度。 2. 同样,正如您在输出中清楚地看到的那样,有些块太小了!如果没有周围的上下文,单个单词 chunks 没有任何意义。 3. 行间中断:根据提出的问题检索一个块,但如果我们在句子中间截断一个句子/行,它就完全不完整,甚至具有不同的含义。 让我们尝试一一解决这些问题。 ## 2. 修复了窗口分块 让我们首先解决第一个问题,即块大小太长或太短。这次我们接受大小限制,并尝试在达到大小时准确拆分文本。 ``` def fixed_window_splitter(text: str, chunk_size: int = 1000) -> List[str]: """Splits text at given chunk_size""" splits = [] for i in range(0, len(text), chunk_size): splits.append(text[i:i + chunk_size]) return splits ``` ![img](https://yg9538.kmgy.top/20241209170344083.png) fixed_window_splitter 的输出 我们确实解决了 chunk 的最小和最大边界,因为它总是会chunk_size。但单词之间的中断仍然保持不变。从输出中我们可以看到,我们正在失去块的含义,因为它在句子中间被分割。 ## 3. 修复了具有重叠分块的窗口 确保我们不会在单词之间分裂的最简单方法是确保我们遍历到单词的末尾,然后停止。虽然这会使上下文不会太长,并且在预期的chunk_size范围内,但更好的方法是在实际开始位置后面开始下一个块的一些字符/单词/标记,以便上下文始终保留并且是连续的。`x` ``` def fixed_window_with_overlap_splitter(text: str, chunk_size: int = 1000, chunk_overlap: int = 10) -> List[str]: """Splits text at given chunk_size, and starts next chunk from start - chunk_overlap position""" chunks = [] start = 0 while start <= len(text): end = start + chunk_size chunks.append(text[start:end]) start = end - chunk_overlap return chunks ``` ![img](https://yg9538.kmgy.top/20241209170344242.png) fixed_window_with_overlap_splitter 的输出 ## 4. 递归字符分块 有了 和 fixed,我们现在就可以解决单词中间或句子中间拆分的问题。这可以通过对我们最初的 Naive splitter 进行一些修改来解决。我们获取一个 separator 列表,并在我们增长到 chunk 大小时选择一个好的 separator。同时,我们仍将继续使用相同的数据块重叠。这是 LangChain 包中最受欢迎的拆分器之一,称为 [RecursiveCharacterTextSplitter](https://github.com/langchain-ai/langchain/blob/82b5b77940e97f65179efa0268031c47d0584a1c/libs/text-splitters/langchain_text_splitters/character.py#L58)。这与我们的方法相同:`Chunk Size``Chunk Overlap` 1. 从最高优先级分隔符开始,该分隔符从开头 *\n\n* 开始,然后移动到*分隔符*列表中的下一个。 2. 如果拆分超过chunk_size,它将应用下一个分隔符,直到当前拆分小于正确的大小。 3. 下一次分割从当前分割结尾后面的 chunk_overlap 个字符开始,从而保持上下文的连续性。 ![img](https://yg9538.kmgy.top/20241209170344178.png) recursive_character_splitter 的输出 ## 4. 语义分块 到目前为止,我们只考虑了在何处拆分数据,无论是在段落末尾、换行符、制表符还是其他分隔符。但是我们还没有考虑何时拆分,即如何更好地捕获有意义的 chunk,而不仅仅是某个长度的 chunk。这种方法称为语义分块。让我们使用 [Flair](https://github.com/flairNLP/flair) 来检测句子边界或特定实体并创建有意义的块。使用 *SegtokSentenceSplitter* 将文本拆分为句子,这可确保在有意义的边界处拆分文本。我们保持大小调整逻辑不变,进行分组,直到达到*chunk_overlap的chunk_size*重叠和重叠,以确保保持上下文。 ``` def semantic_splitter(text: str, chunk_size: int = 1000, chunk_overlap: int = 10) -> List[str]: from flair.models import SequenceTagger from flair.data import Sentence from flair.splitter import SegtokSentenceSplitter splitter = SegtokSentenceSplitter() # Split text into sentences sentences = splitter.split(text) chunks = [] current_chunk = "" for sentence in sentences: # Add sentence to the current chunk if len(current_chunk) + len(sentence.to_plain_string()) <= chunk_size: current_chunk += " " + sentence.to_plain_string() else: # If adding the next sentence exceeds max size, start a new chunk chunks.append(current_chunk.strip()) current_chunk = sentence.to_plain_string() # Add the last chunk if it exists if current_chunk: chunks.append(current_chunk.strip()) return chunks ``` ![img](https://yg9538.kmgy.top/20241209170346208.png) semantic_splitter 的输出 LangChain 有两个这样的拆分器,使用 [NLTK](https://github.com/langchain-ai/langchain/blob/master/libs/text-splitters/langchain_text_splitters/nltk.py) 和 [spaCy](https://github.com/langchain-ai/langchain/blob/master/libs/text-splitters/langchain_text_splitters/spacy.py) 库,所以一定要看看它们。 因此,一般来说,在静态分块方法中,是确定分块策略时要考虑的两个主要因素。Chunk size 是每个块的字符/单词/标记的数量,chunk overlap 是当前块中要包含的前一个块的数量,因此上下文是连续的。块重叠也可以表示为字符/单词/标记的数量或块大小的百分比。`Chunk Size``Chunk Overlap` 您可以使用很酷的 [ChunkViz](https://github.com/gkamradt/ChunkViz) 工具来可视化不同的分块策略在不同的数据块大小和重叠参数下的行为: ![img](https://yg9538.kmgy.top/20241209170346778.png) [ChunkViz](https://github.com/gkamradt/ChunkViz) 上的 Hound Of Baskervilles ## 5. 嵌入分块 尽管语义分块可以完成工作,但 NLTK、spaCy 或 Flair 使用自己的模型/嵌入来理解给定的数据,并尝试为我们提供数据在语义上可以最佳分割的时间。当我们继续进行实际的 RAG 实现时,我们的 embeddings 可能与我们的 chunks 合并在一起的 embedding 不同,因此可以完全以不同的方式理解。因此,在这种方法中,我们首先拆分为句子,并根据我们稍后将用于 RAG 检索的相同嵌入模型形成块。为了以不同的方式做事,我们将使用 NLTK for 来拆分为句子,并使用 OpenAIEmbeddings 将它们合并以形成句子。 ``` def embedding_splitter(text_data, chunk_size=400): import os import nltk from langchain_openai.embeddings import AzureOpenAIEmbeddings from sklearn.metrics.pairwise import cosine_similarity import numpy as np from dotenv import load_dotenv, find_dotenv from tqdm import tqdm from flair.splitter import SegtokSentenceSplitter load_dotenv(find_dotenv()) # Set Azure OpenAI API environment variables (ensure these are set in your environment) # You can also set these in your environment directly # os.environ["OPENAI_API_KEY"] = "your-azure-openai-api-key" # os.environ["OPENAI_API_BASE"] = "your-azure-openai-api-endpoint" os.environ["OPENAI_API_VERSION"] = "2023-05-15" # Initialize OpenAIEmbeddings using LangChain's Azure support embedding_model = AzureOpenAIEmbeddings(deployment="text-embedding-ada-002-01") # Use your Azure model name # Step 1: Split the text into sentences def split_into_sentences(text): splitter = SegtokSentenceSplitter() # Split text into sentences sentences = splitter.split(text) sentence_str = [] for sentence in sentences: sentence_str.append(sentence.to_plain_string()) return sentence_str[:100] # Step 2: Get embeddings for each sentence using the same Azure embedding model def get_embeddings(sentences): embeddings = [] for sentence in tqdm(sentences, desc="Generating embeddings"): embedding = embedding_model.embed_documents([sentence]) # Embeds a single sentence embeddings.append(embedding[0]) # embed_documents returns a list, so take the first element return embeddings # Step 3: Form chunks based on sentence embeddings, a similarity threshold, and a max chunk character size def form_chunks(sentences, embeddings, similarity_threshold=0.7, chunk_size=500): chunks = [] current_chunk = [] current_chunk_emb = [] current_chunk_length = 0 # Track the character length of the current chunk for i, (sentence, emb) in enumerate(zip(sentences, embeddings)): emb = np.array(emb) # Ensure the embedding is a numpy array sentence_length = len(sentence) # Calculate the length of the sentence if current_chunk: # Calculate similarity with the current chunk's embedding (mean of embeddings in the chunk) chunk_emb = np.mean(np.array(current_chunk_emb), axis=0).reshape(1, -1) # Average embedding of the chunk similarity = cosine_similarity(emb.reshape(1, -1), chunk_emb)[0][0] if similarity < similarity_threshold or current_chunk_length + sentence_length > chunk_size: # If similarity is below threshold or adding this sentence exceeds max chunk size, create a new chunk chunks.append(current_chunk) current_chunk = [sentence] current_chunk_emb = [emb] current_chunk_length = sentence_length # Reset chunk length else: # Else, add sentence to the current chunk current_chunk.append(sentence) current_chunk_emb.append(emb) current_chunk_length += sentence_length # Update chunk length else: current_chunk.append(sentence) current_chunk_emb = [emb] current_chunk_length = sentence_length # Set initial chunk length # Add the last chunk if current_chunk: chunks.append(current_chunk) return chunks # Apply the sentence splitting sentences = split_into_sentences(text_data) # Get sentence embeddings embeddings = get_embeddings(sentences) # Form chunks based on embeddings chunks = form_chunks(sentences, embeddings, chunk_size=chunk_size) return chunks ``` ![img](https://yg9538.kmgy.top/20241209170346426.png) embedding_splitter 的输出 ## 6. 代理分块 我们的 Embedding Chunking 应该更接近于使用创建的嵌入的余弦相似性来分割数据。虽然这效果很好,但我们有一个主要缺点:它无法理解文本的语义。“I Like You” 与 “I ***Like\*** You” 对 “like” 的讽刺,这两个句子将具有相同的嵌入,因此在计算时将对应于相同的余弦距离。这就是 Agentic(或基于 LLM)分块派上用场的地方。它分析内容,以根据独立性和语义一致性确定逻辑中断点。 ``` def agentic_chunking(text_data): from langchain_openai import AzureChatOpenAI from langchain.prompts import PromptTemplate from langchain llm = AzureChatOpenAI(model="gpt-4o", api_version="2023-03-15-preview", verbose=True, temperature=1) prompt = """I am providing a document below. Please split the document into chunks that maintain semantic coherence and ensure that each chunk represents a complete and meaningful unit of information. Each chunk should stand alone, preserving the context and meaning without splitting key ideas across chunks. Use your understanding of the content’s structure, topics, and flow to identify natural breakpoints in the text. Ensure that no chunk exceeds 1000 characters length, and prioritize keeping related concepts or sections together. Do not modify the document, just split to chunks and return them as an array of strings, where each string is one chunk of the document. Return the entire book not dont stop in betweek some sentences. Document: {document} """ prompt_template = PromptTemplate.from_template(prompt) chain = prompt_template | llm result = chain.invoke({"document": text_data}) return result ``` # 评估 我们将在即将发布的文章中介绍 RAG 评估技术;在这篇文章中,我们将看到 [RAGAS](https://docs.ragas.io/en/stable/) 定义的两个指标,以及 ,它们决定了我们的分块策略的表现。`context_precision``context_relevance` > [Context Precision (上下文精度](https://docs.ragas.io/en/stable/concepts/metrics/context_precision.html)) 是一个指标,用于评估上下文中存在的所有与真实相关的项目是否排名较高。理想情况下,所有相关的 chunk 都必须出现在最高排名中。此指标是使用 question、ground_truth 和 contexts 计算的,值范围介于 0 和 1 之间,其中分数越高表示精度越高。 > > [Context Relevancy](https://docs.ragas.io/en/v0.1.6/concepts/metrics/context_relevancy.html) 衡量检索到的上下文的相关性,根据问题和上下文进行计算。这些值在 (0, 1) 范围内,值越高表示相关性越高。 在下一篇文章中,我们将介绍提案检索,这是代理拆分方法之一,并计算所有策略的 RAGAS 指标。 # 结论 在本文中,我们介绍了为什么需要分块,并培养了一种直觉来构建一些策略及其实现,以及在一些知名库中构建它们的相应代码。这些只是基本的分块策略,尽管每天都在发明越来越多的策略,以使更好的检索变得更好。
yg9538
2024年12月9日 17:08
63
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
PDF文档
PDF文档(打印)
分享
链接
类型
密码
更新密码