当前位置: 首页 > news >正文

langchain 入门指南 - 文本分片及向量化

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。

前面的内容中关于数据或者上下文的传递我们都是通过 Prompt 来完成的,而这样我们会面临以下挑战:

  1. Prompt 的内容大小限制:成本,处理耗时
  2. 使用大量数据的成本
  3. 并非所有数据都会用于解决当前问题

解决大量数据/文本的设想 - 分治

分割成数据块 -> 选取相关数据块(多次) -> 发送至大模型

如何根据用户的问题选择相关的数据块?

有一种办法就是:使用语义检索。(不同于关键词检索,关键词检索是要严格匹配上关键词才能检索,但语义检索可以检索到相关的文本)

语义检索是一种基于文本内容和意义的信息检索方法,它试图理解查询和文档的语义,
以便更准确地找到与查询相关地文档。

向量化(embedding) 是将文本数据转换为数值向量的过程。向量化后的文本可以用于计算文本之间的相似性,
如余弦相似度、欧几里得距离等度量。这使得语义检索能够根据查询和文档之间的语义相似性来对文档进行排序和检索,从而提高检索的准确性和效率。

embedding 示例 - 计算相似性

下面的例子中,我们会看到 np.dot(embedding1, embedding3) 的值是最大的,这说明 sentence1sentence3 的相似性最高。

from langchain_openai import OpenAIEmbeddingsimport os
os.environ['OPENAI_API_KEY'] = "your key"
os.environ['OPENAI_BASE_URL'] = "https://api.openai-hk.com/v1"embedding = OpenAIEmbeddings()
sentence1 = "我是一名软件工程师"
sentence2 = "小张从事法律工作"
sentence3 = "我是一名程序员"embedding1 = embedding.embed_query(sentence1)
embedding2 = embedding.embed_query(sentence2)
embedding3 = embedding.embed_query(sentence3)import numpy as np
print(np.dot(embedding1, embedding2))
print(np.dot(embedding1, embedding3))
print(np.dot(embedding2, embedding3))

输出:

0.7987314936103257
0.9586440032651322
0.7990728512968016

numpy.dot 方法用于在机器学习中衡量两个向量的相似度。点积越大,两个向量越相似。

处理大文本

我们可以使用如下函数对我们的文本进行切割:

def split_file_into_chunks(file_path, chunk_size):chunks = []with open(file_path, 'r', encoding='utf-8') as file:while True:chunk = file.read(chunk_size)if not chunk:breakchunks.append(chunk)return chunksprint(split_file_into_chunks('service_design.txt', 100))

向量化

然后,我们可以对每个文本块进行向量化:

from langchain_openai import OpenAIEmbeddings
def embed(chunks):embedding = OpenAIEmbeddings()return [embedding.embed_query(chunk) for chunk in chunks]embeddings = embed(split_file_into_chunks('service_design.txt', 100))

向量检索

最后,我们可以使用向量检索来找到与查询最相关的文本块:

def find_k_largest_indices(input_list, k):"""input_list: 点积列表k: 返回前 k 个最大值的索引"""sorted_indices = sorted(range(len(input_list)), key=lambda i: input_list[i], reverse=True)print(input_list)print(sorted_indices)return sorted_indices[:k]def search(chunks, embeddings, top_k, txt):import numpy as npembedding = OpenAIEmbeddings(chunk_size=1)embedded_text = embedding.embed_query(txt)# 计算输入文本与每个分块的相似度distances = [np.dot(embedded_text, emb) for emb in embeddings]# 返回前 k 个最相似的分块的索引ret_idx = find_k_largest_indices(distances, top_k)return [chunks[i] for i in ret_idx]print(search(split_file_into_chunks('service_design.txt', 100), embeddings, 3, "字段长度"))

使用向量检索到的块来作为 prompt

上面通过向量检索拿到相关的文本块之后,我们可以将这一小部分文本块作为上下文传递给大模型。
然后就可以大模型就可以根据这些文本块来回答用户的问题。

这个时候,你就可以针对你的文档内容提问题了。

from openai import OpenAIclient = OpenAI(api_key="your key",base_url="https://api.openai-hk.com/v1"
)def answer_question_with_doc(question, chunks, embeddeds):relevent_chunks = search(chunks, embeddeds, 2, question)prompt = """仅通过总结以下的文字片段回答用户问题,注意保持回答的语义通顺(字数在 30 字以内)---"""for chunks in relevent_chunks:prompt = prompt + "\n'" + chunks + "'"response = client.chat.completions.create(model="gpt-3.5-turbo",messages=[{"role": "system", "content": prompt},{"role": "user", "content": question}],temperature=0.9,max_tokens=200)return response.choices[0].message.contentprint(answer_question_with_doc("如何做字段取舍", split_chunks, embeddings))

输出:

尽可能减少字段暴露,考虑敏感信息如客户地址、手机号等,斟酌是否必要暴露,若必需则考虑脱敏和加解密。

总结

在本文中,我们讨论了如何通过对文本进行切割,然后对这些文本块进行向量化处理,
最后,再对这些文本块做向量化搜索,以找到与查询最相关的文本块。
在搜索到相关的文本块之后,我们可以将这些文本块作为上下文传递给大模型,以回答用户的问题。

优点:

  1. 不用传递大量的文本作为上下文给大模型。节省成本的同时也减少了大模型的处理时间。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 给定日期计算时间(2025新年倒计时)
  • 无涯·问知财报解读,辅助更加明智的决策
  • Vue常用的指令都有哪些?都有什么作用?什么是自定义指令?
  • SSRF学习笔记
  • WordPress原创插件:自定义文章标题颜色
  • 【ESP8684————固件烧录说明、调试记录(1)】
  • OWASP ZAP:一款功能强大的开源Web安全扫描工具
  • 硬件工程师笔面试真题汇总
  • freertos的学习cubemx版
  • Web前端:HTML篇(四)头部head标签与样式表的导入
  • c语言第四天笔记
  • 萝卜快跑:自动驾驶的先锋与挑战
  • unity基础问题
  • 后端开发刷题 | 笔试
  • 【React】详解样式控制:从基础到进阶应用的全面指南
  • 【Leetcode】101. 对称二叉树
  • 5、React组件事件详解
  • Apache Zeppelin在Apache Trafodion上的可视化
  • PHP 使用 Swoole - TaskWorker 实现异步操作 Mysql
  • Traffic-Sign Detection and Classification in the Wild 论文笔记
  • 分享一个自己写的基于canvas的原生js图片爆炸插件
  • 聚簇索引和非聚簇索引
  • 前端面试之CSS3新特性
  • 如何打造100亿SDK累计覆盖量的大数据系统
  • 实战:基于Spring Boot快速开发RESTful风格API接口
  • 项目实战-Api的解决方案
  • No resource identifier found for attribute,RxJava之zip操作符
  • AI又要和人类“对打”,Deepmind宣布《星战Ⅱ》即将开始 ...
  • 数据库巡检项
  • 完善智慧办公建设,小熊U租获京东数千万元A+轮融资 ...
  • ​HTTP与HTTPS:网络通信的安全卫士
  • (博弈 sg入门)kiki's game -- hdu -- 2147
  • (定时器/计数器)中断系统(详解与使用)
  • (附源码)springboot“微印象”在线打印预约系统 毕业设计 061642
  • (一) storm的集群安装与配置
  • (一)Dubbo快速入门、介绍、使用
  • (原)Matlab的svmtrain和svmclassify
  • (转)Oracle存储过程编写经验和优化措施
  • (转)VC++中ondraw在什么时候调用的
  • .MyFile@waifu.club.wis.mkp勒索病毒数据怎么处理|数据解密恢复
  • .naturalWidth 和naturalHeight属性,
  • .net 7和core版 SignalR
  • .net core 依赖注入的基本用发
  • .net core 源码_ASP.NET Core之Identity源码学习
  • .net 获取url的方法
  • .net 写了一个支持重试、熔断和超时策略的 HttpClient 实例池
  • .net6解除文件上传限制。Multipart body length limit 16384 exceeded
  • .NET程序员迈向卓越的必由之路
  • .考试倒计时43天!来提分啦!
  • @Autowired和@Resource装配
  • [8] CUDA之向量点乘和矩阵乘法
  • [BJDCTF2020]The mystery of ip
  • [C#学习笔记]注释
  • [CCIE历程]CCIE # 20604
  • [CentOs7]搭建ftp服务器(2)——添加用户