把浏览器收藏夹搬进的知识库

"收藏了但是从来没看过",经常上网的朋友应该都深有感触。最近在整理收藏夹,突然发现很多收藏还是有价值的,如果只是收藏没有用起来,就显得十分浪费了。那么我们该如何解决这个问题呢?突然在去年的某一天,我突发奇想,能不能利用LLM技术让收藏夹成为我的私人知识库,通过实验验证答案是可以的。

流程图

读取收藏夹

工程化的第一步就是找到收藏夹并读出来,这里我们查阅了资料chrome浏览器的收藏夹一般存放在特定的位置。

在浏览器中输入chrome://version/进入浏览器信息界面,我们看到的个人资料路径就是收藏夹的存放路径啦。

这里我提取到了我的收藏夹路径如下所示。

rust 复制代码
/Users/用户名称/Library/Application Support/Google/Chrome/Default/Bookmarks

找到文件之后,我们就需要解决第二个文件,如何读取收藏夹?

这里找到文件之后必须cat一手,通过读取文件,我们发现Chrome的收藏夹结构是个树,我们只需要按照其结构完成解析即可。

我的解析代码,如下所示。具体思路就是:分层递归解析树。

python 复制代码
# get_bookmark 获取书签
def get_bookmark():
    bookmark_list = []
    unuseful_keyword = ['登录页'] # list
    unuseful_url = ['docs.qq.com', 'doc.weixin.qq.com'] # list
    def parse_bookmarks(bookmark_node):
        if 'children' in bookmark_node:
            for child in bookmark_node['children']:
                parse_bookmarks(child)
        else:
            if 'url' in bookmark_node:
                url = bookmark_node['url']
                title = bookmark_node.get('name', 'No title')
                # 提取时间(这里有个坑,Chrome的时间戳是windows时间戳,不是unix的)
                date_added = bookmark_node.get('date_added', 0)
                # 过滤无用url
                if any(item in url for item in unuseful_url):
                    return
                # 过滤无用关键词
                if any(keyword in title for keyword in unuseful_keyword):
                    return
                bookmark_list.append({
                    'title': bookmark_node.get('name', 'No title'),
                    'url': bookmark_node['url'],
                    'date_added': windows_timestamp_to_datetime(date_added),
                })

    bookmarks = read_chrome_bookmarks(path)
    # 从书签数据中提取书签
    if 'roots' in bookmarks:
        for root in bookmarks['roots']:
            parse_bookmarks(bookmarks['roots'][root])

    return bookmark_list
  • 过滤无用url,指的是需要把一些无价值,爬虫无法获取的页面过滤掉。
  • 过滤无用关键词,指的是要过滤掉一些登录页,授权页,以及404 Not Found等。

获取页面内容

第二步就是解析收藏夹的内容,这一步就十分简单了,我们通过python的request库直接访问对应的页面即可,当然如果考虑反爬的话,这里可以考虑使用代理IP,来减少封控。

python 复制代码
def http_request(url):
    headers = {
        'user-agent': UserAgent().get_random_user_agent() # 随机ua
    }
    try:
        resp = requests.get(url, headers=headers)
        if resp.status_code == HTTPStatus.OK:
            try:
                return resp_encode(resp)
            except:
                return resp.text
        logger.warning(f"网页抓取失败, url: {url}")
        return ""
    except Exception as e:
        logger.error(f"网页抓取失败, url: {url}, error: {e}")
        return ""

获取到正文之后,我们通过trafilatura抽取网页正文,以获得网页的内容,具体代码也很简单如下所示。(这里目前的抽取其实比较简单粗暴,后续会切为基于正文区域的抽取,具体逻辑作者还在实验中)

python 复制代码
def html_extract(html_text):
    txt = trafilatura.extract(html_text, include_tables=False, output_format="txt")
    if not txt:
        return None
    return txt

LLM抽取关键词

完成正文抽取过后,我计划使用LLM来抽取正文的关键词,不得不说LLM的发展真的日新月异,半年前我在做网站勘探的时候LLM抽取的关键词还出现幻觉,抽取质量不高的情况,当我最近有开始使用的时候,发现模型的抽取能力已经有了一个巨大的提升,下面是一个抽取效果:

原文

蚂蚁集团的企业级产品是一个庞大且复杂的系统,数量多且功能复杂,而且变动和并发频繁,常常需要设计者与开发者能快速做出响应。同时这类产品中存在很多类似的页面以及组件,我们可以通过抽象得到一些稳定且高复用性的内容。

我们提供完善的设计指引、最佳实践、设计资源和设计工具,来帮助设计者快速产出高质量产品原型。

我们采用 React 封装了一套 Ant Design 的组件库,也欢迎社区其他框架的实现版本。

如果你的公司和产品使用了 Ant Design,欢迎到 这里 留言。

我们欢迎任何形式的贡献,有任何建议或意见,请给我们 提问。

关键词

"前端开发","React","设计系统","工具","AntDesign","用户体验"

关键词很好的概括了上面的原文,恰好满足我们的需求,PS:这里的模型选择的是qwen系列的文生文模型。

向量化

这里我选择了huggingface.co/BAAI/bge-m3作为向量化的模型,选型原因如下:

1.支持多语言(网页内容涵盖了中英)。

2.开源(免费!!!)。

3.milvus对他有良好的适配。

一些准备就绪过后,我们开始定义我们需要存储的数据,大概的schema是这样的。

ini 复制代码
schema = MilvusClient.create_schema(
        auto_id=False,
        enable_dynamic_field=True,
        description="bookmark list",
    )
    schema.add_field(field_name="id", datatype=DataType.INT64, is_primary=True, auto_id=True)
    schema.add_field(field_name="title", datatype=DataType.VARCHAR, max_length=4000)
    schema.add_field(field_name="text", datatype=DataType.VARCHAR, max_length=10000)
    schema.add_field(field_name="tags", datatype=DataType.ARRAY, element_type=DataType.VARCHAR, max_capacity=50, max_length=100) # 最多50个关键词
    schema.add_field(field_name="text_embedding", datatype=DataType.FLOAT_VECTOR, dim=DIM) # 密集向量
    schema.add_field(field_name="tags_embedding", datatype=DataType.SPARSE_FLOAT_VECTOR) # 稀疏向量

我们定义了两种向量,分别用于不同数据源的检索,内容使用密集向量,标签使用稀疏向量。至此我们就完成了录入知识库的前序操作。(此处省略了环境安装如有疑问欢迎咨询)

然后就是开始了漫长的入库工作,1000个链接大约用了60分钟。

入库效果:

查询效果

完成了上述设计之后,我们尝试下检索效果,看着还行,至此一个简单的查询收藏夹工程化便完成了。

优化方向

由于时间匆忙,本周仅仅是完成了一个粗糙的demo,此处仍还有很多可以提升的地方,下面是我的两个方向。

  • 抽取正文更加准确,目前抽取是一个比较粗糙的全文抽取,影响大模型的关键词抽取,以及检索的准召,后续作者将采用正文识别算法(研究中),找到网页的正文区域,精准抽取。
  • 尝试更多的rerank算法,提高召回质量。

如果有更好的想法,欢迎交流沟通,一起做点有趣的东西~~

相关推荐
hao_wujing3 小时前
深度学习网络入侵检测系统警报
人工智能·深度学习
L-ololois4 小时前
【AI】模型vs算法(以自动驾驶为例)
人工智能·算法·自动驾驶
编程乐学(Arfan开发工程师)5 小时前
56、原生组件注入-原生注解与Spring方式注入
java·前端·后端·spring·tensorflow·bug·lua
猎嘤一号5 小时前
使用 PyTorch 和 SwanLab 实时可视化模型训练
人工智能·pytorch·深度学习
Jay Kay5 小时前
论文阅读:强化预训练
人工智能·语言模型·自然语言处理
Elcker7 小时前
Springboot+idea热更新
spring boot·后端·intellij-idea
蹦蹦跳跳真可爱5897 小时前
Python----神经网络发(神经网络发展历程)
人工智能·python·深度学习·神经网络·计算机视觉
学步_技术7 小时前
增强现实—Flame: Learning to navigate with multimodal llm in urban environments
人工智能·机器学习·计算机视觉·语言模型·自然语言处理·ar
飞飞是甜咖啡7 小时前
【机器学习】Teacher-Student框架
人工智能·算法·机器学习
愿所愿皆可成7 小时前
机器学习之集成学习
人工智能·随机森林·机器学习·集成学习