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

"收藏了但是从来没看过",经常上网的朋友应该都深有感触。最近在整理收藏夹,突然发现很多收藏还是有价值的,如果只是收藏没有用起来,就显得十分浪费了。那么我们该如何解决这个问题呢?突然在去年的某一天,我突发奇想,能不能利用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算法,提高召回质量。

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

相关推荐
赣州云智科技的技术铺子10 分钟前
【一步步开发AI运动APP】六、运动计时计数能调用
人工智能·程序员
东临碣石8211 分钟前
【AI论文】什么、如何、何处以及效果如何?大语言模型测试时缩放技术调研
人工智能
lamdaxu11 分钟前
02Tomcat 线程模型详解&性能调优
后端
猪猪的超超13 分钟前
从吉卜力漫画到艺术创造:GPT-4o多种风格绘图Prompt大全
人工智能·prompt·文生图·gpt-4o
lamdaxu14 分钟前
03Tomcat类加载机制&热加载和热部署
后端
带娃的IT创业者15 分钟前
《AI大模型应知应会100篇》第7篇:Prompt Engineering基础:如何与大模型有效沟通
人工智能·prompt
网络研究院17 分钟前
ChatGPT 的新图像生成器非常擅长伪造收据
网络·人工智能·安全·chatgpt·风险·技术·欺诈
程序猿chen18 分钟前
《JVM考古现场(十五):熵火燎原——从量子递归到热寂晶壁的代码涅槃》
java·jvm·git·后端·java-ee·区块链·量子计算
Blossom.11820 分钟前
边缘计算:工业自动化的智能新引擎
人工智能·5g·自动化·边缘计算·database·兼容性·5g通讯
jndingxin40 分钟前
OpenCV 图形API(10)用于执行标量除以矩阵的逐元素操作函数divRC()
人工智能·opencv