1、项目简介
本项目是一个基于大模型的豆瓣图书搜索推荐系统。该系统接收用户输入的URL或文本段落,利用Facebook AI Similarity Search(FAISS)进行索引搜索,并返回数据库中最相似的图书链接。如果输入的是URL,系统将自动运行爬虫抓取书籍信息。所有输入的文本将默认使用Bart模型(或T5模型)进行摘要处理,并通过SentenceTransformer进行编码,将句子和段落映射到384维的密集向量空间。然后,索引搜索算法将比较输入向量和数据库中的向量,返回最相似的前5个结果。最终输出将根据索引从数据集中检索。
1.1 技术栈
-
后端框架:Flask
-
大模型:Bart模型、T5模型、SentenceTransformer
-
索引和搜索:Facebook AI Similarity Search (FAISS)
-
网页爬虫:requests、lxml、etree
-
数据处理:pandas
1.2 实现功能
-
用户输入处理:
-
接收用户输入的URL或文本段落。
-
使用爬虫抓取书籍信息(如果输入为URL)。
-
预处理输入文本,生成摘要并进行编码。
-
-
向量编码:
-
使用Bart模型或T5模型生成输入文本的摘要。
-
使用SentenceTransformer将文本映射到384维的向量空间。
-
-
索引和相似度搜索:
-
使用FAISS进行向量索引和相似度搜索。
-
返回数据库中与输入最相似的前5个结果。
-
-
用户界面:
-
提供简单易用的Web界面,用户可以输入URL或文本段落进行搜索。
-
返回搜索结果,包括书籍的链接和相关信息。
-
2、部分截图
2.1 架构图
2.2 运行截图
3、部分代码
3.1 爬虫代码
# https://book.douban.com/tag/
# 要爬取的 豆瓣读书中的 图书分类名称
kinds = ['小说', '文学']
for book_kind in kinds:
# 为每个分类创建一个DataFrame
data = []
# 每个标签最多50页
for i in range(1, 51):
print('{name} 开始爬取第 {index} 页'.format(name=book_kind, index=i))
# 拼接url
url = 'https://book.douban.com/tag/{name}?start={num}&type=T'.format(name=book_kind, num=i * 20 - 20)
print(url)
headers = header_x()
resp = requests.get(url, headers=headers)
html = etree.HTML(resp.text)
lis = html.xpath("//div[@id='subject_list']/ul/li")
for li in lis:
try:
name = li.xpath("./div[@class='info']/h2/a/@title") # 书名
img_url = li.xpath("./div[@class='pic']/a/@href") # 缩略图链接
author = li.xpath("./div[@class='info']/div[@class='pub']/text()")[0].strip().split('/')[0] # 作者
publisher = li.xpath("./div[@class='info']/div[@class='pub']/text()")[0].strip().split('/')[-3] # 出版社
publish_time = li.xpath("./div[@class='info']/div[@class='pub']/text()")[0].strip().split('/')[
-2] # 出版年
# 判断出版社,出版年份是否在指定位置 如果不在 则跳过
if (publish_time.find('-') == -1):
continue
grade = li.xpath(".//span[@class='pl']/text()")[0].strip() # 评价数
# 处理grade 提取数字
grade_num = []
grade_num = re.findall("\d+\.?\d*", grade)
intro_1 = li.xpath("./div[@class='info']/p/text()")[0].strip() # 小简介
# 子链接
son_url = li.xpath("./div[@class='info']/h2/a/@href")[0] # 子链接
resp_son = requests.get(son_url, headers=headers)
html_son = etree.HTML(resp_son.text)
# 评分
score = html_son.xpath("//strong[@class='ll rating_num ']/text()")[0].strip()
# 简介
intro = ''.join(html_son.xpath("//div[@id='link-report']//div[@class='intro']/p/text()"))
# 作者简介
author_intro = ''.join(html_son.xpath("//div[@class='indent ']//div[@class='']/div/p/text()"))
# 标签
label = html_son.xpath("//div[@id='db-tags-section']//a/text()")
label = ' '.join(label)
except IndexError:
continue
3.2 图书编码
def process_and_encode_book(texts, model_name='T5'):
# Check if input is a list
if isinstance(texts, str):
raise TypeError("Input cannot be str")
summaries = []
embeddings = []
# Use tqdm for the progress bar
for i, text in tqdm(enumerate(texts), total=len(texts), desc="Processing books"):
# Preprocess, summarize, and encode each book
preprocessed_text = preprocess_text(text)
summary = summarize_text(preprocessed_text, model_name)
embedding = encode_text(summary)
summaries.append(summary)
embeddings.append(embedding)
return summaries, embeddings
3.3 URL编码
def process_and_encode_url(urls, model_name='T5'):
if isinstance(texts, str):
raise TypeError("Input can not be str")
summaries = []
embeddings = []
for i,url in enumerate(urls):
print(f'Start embedding...{i}')
text = download_parse_book(url)
preprocessed_text = preprocess_text(text)
summary = summarize_text(preprocessed_text, model_name)
embedding = encode_text(summary)
summaries.append(summary)
embeddings.append(embedding)
return summaries, embeddings
3.4 计算返回
index = get_index()
D, I = similarity_search(embedding[0].reshape(1,-1), 5, index)
df =read_from_local_partitions(I[0], 990)
result = {i:j for i,j in zip(df['headline'],df['link'])}
return render_template('results.html', results= result)
4、最后