import
一、引言在向用户推荐相关内容这件事上, 内容平台发展得极为迅速, 平台所提供的相关内容数目越多, 用户于网站之上停留的时长便会越长, 而这一般情况下会转变为公司所需的广告收入。假使你往昔曾访问过新闻网站, 或者电子出版社, 又或者博客平台, 那么你大概率已然接触过推荐引擎。每一个平台都会依据你的那阅读历史记录, 去推荐你有可能会喜欢的内容。罗列出一个较为简易的解决办法, 有一个平台能够达成一个基于标签现象的将物品呈现给用户为之推荐的引擎, 打比方说, 你阅读查看过一篇标明是「商业」范畴的文章, 其还会给你介绍推选五篇被标记住是「商业」领域特性的有相关性的文章。可是, 可以用来构架推举引擎的更为优良的办法路径是运用具备相似性的搜索以及借助机器学习的相关计算准则法子。于本文里, 我们要构建一个Flask应用程序, 此应用程序会借助一个相似性搜索的服务, 去创建属于我们自身的文章推荐引擎。二、源代码解析演示应用程序概览如下简短动画, 演示了我们应用程序的工作方式。最初, 页面上显示着十篇文章, 用户能够选择这十篇文章的任意组合, 来代表他们的阅读历史。当用户点击提交按钮时, 阅读历史会作为输入数据, 用于查询文章数据库, 随后再向用户显示十篇相关文章。能够瞧见, 所返回的相关文章极为精准于这个示例之中, 存在1,024种有可能性的阅读历史组合可被用作输入, 而且每一种组合都会生成有意义的成果。那么我们是如何做到的呢构建应用程序之际, 我们先是从某处找到了一个新闻文章数据集, 此数据集涵盖来自15个主要出版社的143,000篇新闻文章, 然而我们仅仅选用了前面的20,000篇, 完整数据集包含超过200万篇文章呢之后, 我们对数据集进行清理, 是通过重命名几列, 还删除了不必要的列来达成的。接下来, 我们把文章输入到模型当中, 目的是获取各文章的向量, 而这向量可是机器学习算法用来确定各种输入之间相似性的元数据。我们所使用的是平均词嵌入模型。然后, 我们把这些向量插入到由管理的向量索引里。向量被添加到索引之后, 我们便能够着手查找相关内容了。用户提交其阅读历史之际, 会向 API 端点发送一个请求, 此端点借助的 SDK 去查询向量的索引, 端点继而返回十篇类同的新闻文章并于应用程序的 UI 中予以显示, 如此而已这是不是相当简单呢?要是你打算亲自去尝试一回, 你能够在此处寻获该应用程序的源码。于其中涵盖了怎样在本地设备之上运行应用程序的指示以及说明。代码实现我们已然知晓了应用程序的内在工作原理, 然而我们实际上究竟是怎样构建它的呢。如前文所讲, 这是一个借助SDK的Flask应用程序。HTML运用模板文件, 前端剩下的部分借助静态CSS来构建。为了简便起见, 所有后端代码都在app.py文件里, 我把该文件完整地照抄在了下面:from dotenv import load_dotenv from flask import Flask from flask import render_template from flask import request from flask import url_for import json import os import pandas as pd import pinecone import re import requests from sentence_transformers import SentenceTransformer from statistics import mean import swifter app Flask(__name__) PINECONE_INDEX_NAME article-recommendation-service DATA_FILE articles.csv NROWS 20000 def initialize_pinecone(): load_dotenv() PINECONE_API_KEY os.environ[PINECONE_API_KEY] pinecone.init(api_keyPINECONE_API_KEY) def delete_existing_pinecone_index(): if PINECONE_INDEX_NAME in pinecone.list_indexes(): pinecone.delete_index(PINECONE_INDEX_NAME) def create_pinecone_index(): pinecone.create_index(namePINECONE_INDEX_NAME, metriccosine, shards1) pinecone_index pinecone.Index(namePINECONE_INDEX_NAME) return pinecone_index def create_model(): model SentenceTransformer(average_word_embeddings_komninos) return model def prepare_data(data): # 重命名 id 列并删除不必要的列 data.rename(columns{Unnamed: 0: article_id}, inplace True) data.drop(columns[date], inplace True) # 仅提取每篇文章的前几句话以加快向量的计算 data[content] data[content].fillna() data[content] data.content.swifter.apply(lambda x: .join(re.split(r(?[.:;])\s, x)[:4])) data[title_and_content] data[title] data[content] # 基于标题列和文章列创建 embedding 向量 encoded_articles model.encode(data[title_and_content], show_progress_barTrue) data[article_vector] pd.Series(encoded_articles.tolist()) return data def upload_items(data): items_to_upload [(row.id, row.article_vector) for i, row in data.iterrows()] pinecone_index.upsert(itemsitems_to_upload) def process_file(filename): data pd.read_csv(filename, nrowsNROWS) data prepare_data(data) upload_items(data) pinecone_index.info() return data def map_titles(data): return dict(zip(uploaded_data.id, uploaded_data.title)) def map_publications(data): return dict(zip(uploaded_data.id, uploaded_data.publication)) def query_pinecone(reading_history_ids): reading_history_ids_list list(map(int, reading_history_ids.split(,))) reading_history_articles uploaded_data.loc[uploaded_data[id].isin(reading_history_ids_list)] article_vectors reading_history_articles[article_vector] reading_history_vector [*map(mean, zip(*article_vectors))] query_results pinecone_index.query(queries[reading_history_vector], top_k10) res query_results[0] results_list [] for idx, _id in enumerate(res.ids): results_list.append({ id: _id, title: titles_mapped[int(_id)], publication: publications_mapped[int(_id)], score: res.scores[idx], }) return json.dumps(results_list) initialize_pinecone() delete_existing_pinecone_index() pinecone_index create_pinecone_index() model create_model() uploaded_data process_file(filenameDATA_FILE) titles_mapped map_titles(uploaded_data) publications_mapped map_publications(uploaded_data) app.route(/) def index(): return render_template(index.html) app.route(/api/search, methods[POST, GET]) def search(): if request.method POST: return query_pinecone(request.form.history) if request.method GET: return query_pinecone(request.args.get(history, )) return Only GET and POST methods are allowed for this endpoint app.run()我们来进行一下 app.py 文件重要部分的回顾, 从而使我们能够对其加以理解。在第一行到第十四行的范围之内, 我们将应用程序的那些依赖给引入进来 , 接下来要说的是, 我们的这个应用程序依附着以下这些包用于从 .env 文件中读取环境变量flask 用于设置 Web 应用程序json 用于处理 JSONos 也用于获取环境变量用于处理数据集用于使用 SDKre 用于处理正则表达式RegEx用于发送 API 请求以下载我们的数据集提供了一些方便的统计函数s 用于我们的嵌入模型用于处理 的, 在第16行, 我们给出了一些模板代码, 以此来告知Flask我们应用程序的名称。在第18行, 我们定义了一些常量, 这些常量会在应用程序里被使用其中有索引名称, 它是常量之一, 之后, 我们又定义了数据集的文件名, 这也是常量中的一部分, 并且, 我们明确了要从CSV文件中读取的行数, 这同样属于所定义的常量。在第22行, 我们的方法从.env文件中获取API密钥, 在第23行, 继续使用该密钥, 在第24行, 进行相关操作来初始化, 在第25行, 完成初始化相关事宜。从第27行开始数, 一直数到第29行, 在这个范围内, 我们所拥有的方法, 会在实例当中, 去搜寻那个跟我们当下正在运用的索引, 也就是“--”, 有着相同名字的索引。要是寻找到了已经存在的索引, 那么我们就要把它给删除掉。在第31行, 到第35行, 我们的x方法, 运用我们所挑选的名称“--”, 去创建一个全新的索引, 将余弦相似度用作指标, 数据分片设定为1。从第37行开始至40行这部分, 我们所运用的方法用以借助s库去处理平均词嵌入模型, 之后呢, 我们打算运用此模型针对我们的向量实施编码的操作。在第六十二行之处, 一直到第六十八行那里, 我们所拥有的方法, 会去读取CSV文件, 之后呢, 会调用某些方法, 这某些方法, 就是接下来要提及的两个方法, 这两个方法的介绍, 处于下方的位置。在第42行到第56行的范围里, 我们的那种方法, 是借助重命名第一个那种id列, 还有删除date列, 以此来对数据集实施调整的操作。随后, 它会去抓取每一篇文章的前面四行内容, 并且把这些内容跟文章标题相互结合起来, 进而创建出一个全新的字段, 将这个字段当作是要进行编码的数据。我们能够依据文章的整个正文部分去创建向量, 不过为了让编码的过程能够加快速度, 四行其实就已经足够了。在第58行, 到第60行, 处, 我们的方法, 借助使用我们的模型, 对其展开编码, 以此为每一篇文章, 创建一个向量, 随后, 把向量插入到索引里。在第70行, 到第71行, 再到第72 行, 以及第73行, 还有第74行, 我们的一种方法, 和另一种方法, 创立了一些字典, 这些字典里面包含着标题, 以及出版商, 这样做是为了往后, 能够更加便利地, 利用它们的ID, 去查找文章。上方所描述的每一个方法, 都会于后端应用程序启动这个时候, 在第98行至104行的位置进行调用。而这项工作, 使得我们为最后一步, 也就是依据用户输入去查询索引, 做好相应的准备。在第106行, 到第115行, 再到第116行, 我们给应用程序确定了两条路由, 一条是针对主页路, 另一条是向着API端点路, 主页给出index.html模板文件, 还有和CSS资产, API端点给出查询索引所具备的搜索功能。最后在第76行至96行, 我们的方法会获取用户的阅读历史输入, 接着把它转换为向量, 随后查询索引来查找相似文章。获取/api/端点的时候会调用此方法。每当用户提交新的搜索查询, 这个API都会被调用。对于视觉学习者这里提供一个概述应用程序如何工作的图表三、示例场景那么, 把所有的这些整合在一起, 用户体验究竟怎样呢? 我们来看三个场景, 是分别对体育、技术以及政治感兴趣的三群体用户。体育用户把前两篇围绕塞雷娜·威廉姆斯以及安迪·穆雷Andy这两位有名网球运动员的文章选为他们的阅读历史。在进行提交选择之后, 该应用程序会传回有关温布尔登网球锦标赛、美国公开赛、罗杰·费德勒Roger还有拉斐尔·纳达尔Nadal的文章。准确哟

相关新闻

【量化投资从入门到精通 #21】均值回归:在布林下轨捡便宜的纪律

【量化投资从入门到精通 #21】均值回归:在布林下轨捡便宜的纪律

上篇讲趋势(双均线)。这篇讲相反的逻辑——均值回归:价格偏离太远会拉回。一、这个方法解决什么投资问题 趋势策略在震荡市反复挨耳光。均值回归赌的是"跌狠了会弹、涨疯了会落"——适合没有方向的横盘市。 二、核心思想&#xff1…

2026/8/23 23:30:41 阅读更多 →
如何挑选优质陶瓷,让家居焕然一新?

如何挑选优质陶瓷,让家居焕然一新?

挑选优质陶瓷,让家居焕然一新,这事儿可真得好好聊聊。毕竟,瓷砖可是家里的门面担当,选好了不仅美观大方,还能提升居住的舒适度。今天我就结合自己在陶瓷行业摸爬滚打多年的体会,跟大家聊聊如何挑选到称心如…

2026/8/23 23:29:40 阅读更多 →
Meta AI 眼镜走红引担忧:公共场所频遭禁,你能识别身边的它吗?

Meta AI 眼镜走红引担忧:公共场所频遭禁,你能识别身边的它吗?

Meta AI 眼镜走红,隐私风险凸显智能眼镜潮流正盛,每年都有数以百万计的人投身其中。Meta 的 AI 眼镜更是成为了这一潮流中的佼佼者,备受欢迎。然而,其广泛使用也带来了严重的隐私隐患,人们在日常生活中被偷偷录像的可能…

2026/8/23 23:29:40 阅读更多 →

最新新闻

论文AI率过高怎么办?2026年12款免费降AI率工具实测指南

论文AI率过高怎么办?2026年12款免费降AI率工具实测指南

现在毕业论文答辩前,“AI率超标”已经彻底取代“查重率过高”,成了同学们的头号难题!不少同学只是用AI润色了摘要和结论,AI率直接飙升到离谱,纯手动修改根本不管用——这说明AIGC检测系统抓的不是个别词语,…

2026/8/23 23:59:54 阅读更多 →
Marketch:从Sketch画板直接量取CSS

Marketch:从Sketch画板直接量取CSS

Marketch:从Sketch画板直接量取CSS 【免费下载链接】marketch Marketch is a Sketch 3 plug-in for automatically generating html page that can measure and get CSS styles on it. 项目地址: https://gitcode.com/gh_mirrors/ma/marketch 设计稿交付还在…

2026/8/23 23:59:54 阅读更多 →
如何在ThinkPad X390上安装macOS:OpenCore EFI完整指南

如何在ThinkPad X390上安装macOS:OpenCore EFI完整指南

如何在ThinkPad X390上安装macOS:OpenCore EFI完整指南 【免费下载链接】ThinkpadX390-Opencore-EFI macOS Catalina & Big Sur & Monterey on ThinkPad X390 (Hackintosh) 项目地址: https://gitcode.com/gh_mirrors/th/ThinkpadX390-Opencore-EFI …

2026/8/23 23:59:54 阅读更多 →
WechatHook 终极指南:5大核心能力详解,3分钟看懂微信自动化

WechatHook 终极指南:5大核心能力详解,3分钟看懂微信自动化

WechatHook 终极指南:5大核心能力详解,3分钟看懂微信自动化 【免费下载链接】WechatHook Enjoy hooking wechat by Xposed....Accessibility...and so on... 项目地址: https://gitcode.com/gh_mirrors/we/WechatHook WechatHook 是一个基于 Xpos…

2026/8/23 23:59:54 阅读更多 →
OpenModScan:免费跨平台 Modbus 主站调试工具,让现场通讯验证一键搞定

OpenModScan:免费跨平台 Modbus 主站调试工具,让现场通讯验证一键搞定

OpenModScan:免费跨平台 Modbus 主站调试工具,让现场通讯验证一键搞定 【免费下载链接】OpenModScan Open ModScan is a Free Modbus Master (Client) Utility 项目地址: https://gitcode.com/gh_mirrors/op/OpenModScan OpenModScan 是一款开源免…

2026/8/23 23:59:54 阅读更多 →
Gin-JWT认证与授权方案从Token到RBAC权限控制

Gin-JWT认证与授权方案从Token到RBAC权限控制

Gin-JWT认证与授权方案从Token到RBAC权限控制 文章导语 JWT(JSON Web Token)是现代Web服务的身份认证标准。在Gin框架中集成JWT看似简单,但涉及Token刷新、黑名单、多设备登录、RBAC权限控制等实际需求时,就需要更完善的设计。本文…

2026/8/23 23:57:54 阅读更多 →

日新闻

周新闻

[光学原理与应用-521]:对光的错误理解与纠偏

[光学原理与应用-521]:对光的错误理解与纠偏

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

2026/8/24 0:06:02 阅读更多 →
SIP通话转接原理与REFER方法实战解析

SIP通话转接原理与REFER方法实战解析

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

2026/8/24 0:20:20 阅读更多 →
Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

2026/8/24 0:14:11 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/23 18:47:06 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/23 12:10:44 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/22 3:22:48 阅读更多 →