基于论文的大模型应用:基于SmartETL的arXiv论文数据接入与预处理(三)

上一篇 介绍了数据接入处理的整体方案设计。本篇介绍基于SmartETL框架的流程实现。

5. 流程开发

5.1.简单采集流程

从指定时间(yy年 mm月)开始,持续采集arXiv论文。基于月份和顺序号,构造论文ID,进而下载论文PDF文件,保存到本地。

5.1.1.Loader设计

定制开发一个新的Loader“web.ArXivTaskEmit”,基于月份和顺序号构造并输出论文ID。每个月的顺序号从00001到29999。输出格式样例:2503.00001(字符串)。代码如下:

import time
import os
import jsonfrom wikidata_filter.util.dates import current_date
from wikidata_filter.loader.base import DataProviderclass ArXivTaskEmit(DataProvider):ts_file = ".arxiv.ts"def __init__(self, start_month: int = None, end_month: int = None):self.month = start_month or 2501self.seq = 1if os.path.exists(self.ts_file):with open(self.ts_file, encoding="utf8") as fin:nums = json.load(fin)self.month = nums[0]self.seq = nums[1]self.end_month = end_month or int(current_date('%y%m'))print(f"from {self.month}.{self.seq} to {self.end_month}")def write_ts(self):row = [self.month, self.seq]with open(self.ts_file, "w", encoding="utf8") as out:json.dump(row, out)def iter(self):while self.month <= self.end_month:while self.seq < 30000:new_id = f'{self.month}.{self.seq:05d}'print("processing:", new_id)yield new_idself.seq += 1self.write_ts()time.sleep(3)self.month += 1if self.month % 100 > 12:self.month += int(self.month/100)*100 + 101self.seq = 1self.write_ts()

5.1.2.Processor设计

处理过程包括:

  1. 将输入数据包装为dict结构。基于内置ToDict转换算子。转换后,数据变成:{‘d’: ‘2503.00001’}
  2. 构造PDF文件URL。基于内置ConcatFields转换算子。转换后,数据变成:{‘d’: 2503.00001’, ‘url_pdf’: ‘https://arxiv.org/pdf/2503.00001’}
  3. 构造保存本地的文件名。基于内置ConcatFields转换算子。转换后,数据变成:{‘d’: 2503.00001’, ‘url_pdf’: ‘https://arxiv.org/pdf/2503.00001’, ‘filename’: ‘data/arxiv/2503.00001.pdf’}
  4. 判断文件不存在。基于内置Not算子,组合util.files.exists函数。
  5. 文件下载。基于内置Map算子,组合util.http.content函数,将获取的文件内容(bytes类型)作为字段content的值。
  6. 保存文件。基于内置SaveFiles算子。
    上述流程SmartETL的YAML流程定义语法,基于已有的组件进行实例化,并通过Chain进行组合,形成顺序处理流程,完成文件持续下载。

5.1.3.流程定义

name: arXiv简单采集流程
description: 对指定时间范围arXiv论文进行采集loader: web.ArXivTaskEmitnodes:as_dict: ToDictmake_url: ConcatFields('url_pdf', 'd', prefix=’https://arxiv.org/pdf/’)make_filename: ConcatFields('filename', 'd', prefix='data/arxiv/', suffix='.pdf')file_not_exists: Not('util.files.exists', key='filename')download: Map('util.http.content', key='url_pdf', target_key='content', most_times=3, ignore_error=True)save_file: WriteFiles('data/arxiv', name_key=’filename’)processor: Chain(as_dict, make_url, make_filename, file_not_exists, download, save_file)

5.2.论文搜索&HTML采集流程

针对指定关键词,利用arXiv API搜索论文,下载论文HTML页面。

5.2.1.Loader设计

通过命令行的交互输入(input函数)获取关键词作为任务输入。

5.2.2.Processor设计

处理过程包括:

  1. 通过命令行获取用户输入关键词。输出数据为字符串,例如“RAG”。
  2. 基于输入关键词进行检索,基于arXiv官网搜索API进行检索。由于检索结果为XML格式,基于xmltodict库转换为JSON格式,对论文结构附加url_pdfurl_html字段,表示PDF和HTML的下载链接。这一步采用定制开发函数gestata.arxiv.search,配合Map算子进行处理。
  3. 【可选的】数组打散。如果前一步search函数返回为数组结构,则需要通过Flat组件进行打散;如果为生成器yield方式返回,则框架自行处理。
  4. 下载HTML。内置util.http.content函数提供http请求(基于requests库),结合Map算子,实现arxiv HTML文件下载,将获取的文件内容(bytes)作为字段content的值。
  5. 过滤。判断content是否为空,如果网络连接失败或者HTML文件本身不存在,就可以终止。
  6. 保存HTML。将前一步获取的HTML内容(即content字段值)保存为文件。
    搜索核心代码如下:
ARXIV_API_BASE = "http://export.arxiv.org/api/query"
ARXIV_BASE = "http://arxiv.org"def search(topic: str, max_results: int = 50):"""基于arXiv API的论文搜索"""if ':' not in topic:topic = 'all:' + topicparams = {"search_query": topic,"max_results": max_results,"sortBy": "lastUpdatedDate","sortOrder": "descending"}res = requests.get(ARXIV_API_BASE, params=params)doc = xmltodict.parse(res.text)feed = doc.get("feed")if "entry" not in feed:return []papers = feed.get("entry")for paper in papers:_id = paper["id"]_id = _id[_id.rfind('/')+1:]paper["_id"] = _idpaper["url_pdf"] = f"{ARXIV_BASE}/pdf/{_id}"paper["url_html"] = f"{ARXIV_BASE}/html/{_id}"return papers

在SmartETL框架最新设计中,通过将函数动态绑定为处理节点,只需要将业务处理逻辑实现为一个函数,就能够在流程中进行调用,极大方便了数据处理算子开发流程。

5.2.3.流程定义

name: arXiv搜索采集流程
description: 基于用户提供的关键词进行arXiv论文并下载loader: Input('请输入arXiv论文搜索关键词:')nodes:search: Map('gestata.arxiv.search', max_results=10)download: Map('util.http.content', key='url_html', target_key='content', most_times=3, ignore_error=True)filter: FieldsNonEmpty('content')save: WriteFiles('data/arxiv', name_key='_id', suffix='.html')processor: Chain(search, Flat(), download, filter, save)

5.3.HTML解析建索引流程

对下载的HTML页面进行解析,并对论文摘要和正文建立向量化索引。

5.3.1.HTML解析

由于arXiv论文的HTML页面具有特定的网页结构,通过lxml或beaultifulsoup库,可实现对论文标题、作者、章节(包括其中的图片、表格、公示等)列表、附录、参考文献等信息的精准识别。

5.3.2.Loader设计

可直接复用前文所述的自动生成论文ID的“web.ArXivTaskEmit”,也可以采用基于关键词搜索的Input+gestata.arxiv.search

5.3.3.Processor设计

处理过程包括:

  1. HTML解析。设计函数组件gestata.arxiv.extract,从输入的HTML(str类型)中进行论文结构抽取。注意,为了对HTML中的相对链接进行绝对定位,解析HTML时需要提供该HTML的基路径(base path)。此外,设计的函数考虑到可能在其他地方调用,建议提供相关参数配置。
  2. 论文摘要索引。论文摘要是一个单独的字段,并且通常长度较短,符合向量化索引chunk的长度要求,可以通过以下两步建立索引:
    2.1 向量化。通过内置的model.embed.Local组件,调用embedding模型,生成摘要的向量
    2.2 写向量库。利用提前初始化的Qdrant组件,基于内置的DatabaseWriter组件进行写入。
  3. 论文正文索引。论文包括多个章节(section),并且篇幅较长,通常需要进行chunk化拆分。一种简单的方式先按section拆分(避免不同章节的内容成为一个chunk),然后根据段落和句子边界进行长度拆分。过程如下:
    3.1 对sections进行打散,即转成每个section作为一条记录输出。
    3.2 对每个section的content字段进行chunk化拆分并打散
    3.3 向量化。同上。
    3.4 写向量库。同上。

5.3.4.流程定义

name: arXiv论文HTML解析与索引流程
description: 对论文HTML进行解析并建立摘要和正文的向量索引loader: Directory('data/arxiv', '.html')nodes:qd: util.database.qdrant.Qdrant(**qdrant)select: SelectVal('data')extract: Map('gestata.arxiv.extract_from_html')vector1: model.embed.Local(api_base=bge_large_en, key='abstract', target_key='vector')write1: DatabaseWriter(qd, buffer_size=1, collection='chunk_abstract')chain1: Chain(Select('abstract'), vector1, write1)flat: FlatProperty('sections', inherit_props=True)select2: Select('content')chunk: Map('util.split.simple', key='content',target_key='chunks')flat_chunk: Flat(key='chunks')vector2: model.embed.Local(api_base=bge_large_en, key='chunks', target_key='vector')write2: DatabaseWriter(qd, buffer_size=1, collection='chunk_content')chain2: Chain(Select('sections', flat, select2, chunk, flat_chunk, vector2, write2)processor: Chain(select, extract, Fork(chain1, chain2, copy_data=True))

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

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

相关文章

[Swift]Xcode模拟器无法请求http接口问题

1.以前偷懒一直是这样设置 <key>NSAppTransportSecurity</key> <dict><key>NSAllowsArbitraryLoads</key><true/><key>NSAllowsArbitraryLoadsInWebContent</key><true/> </dict> 现在我在Xcode16.3上&#xff…

Python基础总结(八)之循环语句

文章目录 一、for循环1.1 for循环格式1.2 for ...else1.3 for...break1.4 for...continue 二、while循环2.1 while循环格式2.2 while...break2.3 while...continue2.4 while ...else 循环语句就如其名&#xff0c;就是重复的执行一段代码&#xff0c;直到满足退出条件时&#x…

vuex实现同一页面radio-group点击不同按钮显示不同表单

本文实现的是点击单一规格和多规格两个按钮会在页面显示不同的表单 方法一 <!-- 单规格和多规格的切换 --> <el-form label-width"80px" class"text-align-left"><el-form-item label"商品规格"><!-- 监听skus_type的改…

AI编写的“黑科技风格、自动刷新”的看板页面

以下的 index.html 、 script.js 和 styles.css 文件&#xff0c;实现一个具有黑科技风格、自动刷新的能源管理系统实时监控看板。 html页面 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name&q…

Vim使用完全指南:从基础到高效编辑

Vim使用完全指南&#xff1a;从基础到高效编辑 一、Vim简介与基本概念 Vim&#xff08;Vi IMproved&#xff09;是从vi发展出来的一个功能强大的文本编辑器&#xff0c;以其高效性和灵活性著称&#xff0c;特别适合程序开发和系统管理任务。与常规文本编辑器不同&#xff0c;…

时序约束高级进阶使用详解三:Create_Clock

目录 一、前言 二、设计示例 2.1 设计代码 2.2 schematic 2.3 no overwriteing 2.4 约束到非时钟引脚 三、Create_clock应用 3.1 时钟输入端口 3.2 7系列高速收发器输出管脚 3.3 部分原语的输出管脚 3.4 主时钟路径上创建主时钟 3.5 虚拟时钟 3.6 差分时钟的约束 …

箱线图(盒须图)QCPStatiBox

一、QCPStatisticalBox 概述 QCPStatisticalBox 是 QCustomPlot 中用于绘制箱线图(盒须图)的类&#xff0c;可以显示数据的五个关键统计量&#xff1a;最小值、第一四分位数(Q1)、中位数、第三四分位数(Q3)和最大值&#xff0c;以及可能的异常值。 二、主要属性 属性类型描述…

人形机器人马拉松:北京何以孕育“领跑者”?

“机器人每跑一小步&#xff0c;都是人类科技的一大步”&#xff0c;这句对阿姆斯特朗登月名言的仿写&#xff0c;恰如其分地诠释了全球首场人形机器人半程马拉松赛事的里程碑意义。 2025年4月19日&#xff0c;北京亦庄半程马拉松暨人形机器人半程马拉松圆满结束。在总长21.09…

基于Python的推荐算法的电影推荐系统的设计

标题:基于Python的推荐算法的电影推荐系统的设计与实现 内容:1.摘要 本文围绕基于Python的推荐算法的电影推荐系统展开研究。背景在于随着电影数量的急剧增加&#xff0c;用户在海量电影中找到符合自身喜好的影片变得困难。目的是设计并实现一个高效准确的电影推荐系统&#x…

【深度学习】详解矩阵乘法、点积,内积,外积、哈达玛积极其应用|tensor系列02

博主简介&#xff1a;努力学习的22级计算机科学与技术本科生一枚&#x1f338;博主主页&#xff1a; Yaoyao2024往期回顾&#xff1a;【深度学习】你真的理解张量了吗&#xff1f;|标量、向量、矩阵、张量的秩|01每日一言&#x1f33c;: “脑袋想不明白的&#xff0c;就用脚想”…

面试常用基础算法

目录 快速排序归并排序堆排序 n n n皇后问题最大和子数组爬楼梯中心扩展法求最长回文子序列分割回文串动态规划求最长回文子序列最长回文子串单调栈双指针算法修改 分割回文串滑动窗口栈 快速排序 #include <iostream> #include <algorithm>using namespace std;…

相对路径和绝对路径解析

在 Linux/Unix 和文件系统中&#xff0c;绝对路径和相对路径是描述文件或目录位置的两种方式&#xff0c;它们的核心区别在于路径的起点和使用场景。以下是详细对比&#xff1a; 目录 1. 定义与起点 2. 符号与语法 3. 使用场景 4. 实际示例 示例 1&#xff1a;定位文件 示…

【算法数据结构】leetcode37 解数独

37. 解数独 - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a; 题目要求每一行 &#xff0c;每一列&#xff0c;每个3*3 的子框只能出现一次。每个格子的数字范围1-9. 需要遍历每个空格填入可能的数字&#xff0c;并验证符合规则。如果符合就填入&#xff0c;不符…

Vector的学习

vector简介 vector的相关文档对于想深入了解的同学可以参考这个文档进行学习。 vector是表示可变大小数组的序列容器。 就像数组一样&#xff0c;vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问&#xff0c;和数组一样高效。但是又不…

Vue常用指令入门

1. v-for 作用&#xff1a;用于遍历对象或数组 注意&#xff1a;需要提供key属性&#xff0c;可以提高性能和避免渲染错误&#xff0c;值通常为index或item.id <li v-for"(item, index) in items" :key"index">{{ item }} </li>2. v-if,v-el…

在机器视觉检测中为何选择线阵工业相机?

线阵工业相机&#xff0c;顾名思义是成像传感器呈“线”状的。虽然也是二维图像&#xff0c;但极宽&#xff0c;几千个像素的宽度&#xff0c;而高度却只有几个像素的而已。一般在两种情况下使用这种相机&#xff1a; 1. 被测视野为细长的带状&#xff0c;多用于滚筒上检测的问…

线性DP:最长上升子序列(子序列可不连续,子数组必须连续)

目录 Q1&#xff1a;简单遍历 Q2&#xff1a;变式&#xff08;加大数据量&#xff09; Q1&#xff1a;简单遍历 Dp问题 状态表示 f(i,j) 集合所有以第i个数结尾的上升子序列集合-f(i,j)的值存的是什么序列长度最大值max- 状态计算 &#xff08;其实质是集合的划分&#xff09;…

【Web前端技术】第二节—HTML标签(上)

hello&#xff01;好久不见—— 做出一个属于自己的网站&#xff01; 云边有个稻草人-个人主页 Web前端技术—本篇文章所属专栏 目录 一、HTML 语法规范 1.1 基本语法概述 1.2 标签关系 二、HTML 基本结构标签 2.1 第一个 HTML 网页 2.2 基本结构标签总结 三、网页开发…

论文降重GPT指令-实侧有效从98%降低到8%

步骤1&#xff1a;文本接收 指令&#xff1a; 请用户提供需要优化的文本内容。 对文本进行初步分析&#xff0c;识别文本的基本结构和风格。 操作&#xff1a; 接收并分析用户提交的文本。 步骤2&#xff1a;文本优化 2.1 连接词处理 指令&#xff1a; 删除或替换连接词&#x…

Jsp技术入门指南【九】详细讲解JSTL

Jsp技术入门指南【九】详细讲解JSTL 前言一、什么是JSTL&#xff1f;&#xff08;JavaServer Pages Standard Tag Library&#xff09;二、使用JSTL前的准备三、核心标签库常用标签详解1. <c:out>&#xff1a;输出内容&#xff08;替代<% %>&#xff09;2. <c:i…