高级RAG(八): 自动合并检索(Auto-merging Retrieval)

news2024/9/29 15:22:59

自动合并检索(Auto-merging Retrieval)是LlamaIndex的另外一种高级RAG技术,它有点类似与我们之间介绍的从小到大的检索,不过自动合并检索要比“从小到大的检索”稍微复杂一些,它首先将文档按一定的层次结构进行切割,然后在检索的时候将被切割的最小结构也就是叶子节点与问题进行相似度匹配,当一个父节点上的多数叶子节点都与问题匹配上,则将该父节点文档作为context返回给LLM,下面我们先来介绍一下文档的层次结构:

一、文档的层次结构

所谓的文档层次结构是指当我们在切割文档的时候可以按特定的层次结构来进行切割,这里的层次结构可以理解为广度和深度两个维度,我们首先将一个文档切割成若干个较大的文档块,那么这些较大的文档块之间可以理解为是“兄弟关系”,然后我们将每个大文档块再切割成若干个较小的文档块,那么大文档块和小文档块之间就是“父子关系”,而这里的“兄弟关系”可以理解为广度,“父子关系”则可以理解为深度, 为了进一步加深印象,我们可以这样理解:一个长文档可以由若干个章节组成的;每个章节又由多个段落组成,每个段落又可以进一步分割成多个句子,那么章节之间,段落之间,句子之间就是兄弟关系;章节和段落之间,段落和句子之间就是父子关系。下面我们借用github上的DocArray项目来说明文档的层次结构如下图所示:

二、自动合并检索

LlamaIndex的自动合并检索时首先需要将文档按特定的层次结构进行切割,因此先要定义切割的层次结构如[1024,512], 这表示将文档按两层结构进行切割即首先将文档按块大小(chunk_size)为1024进行切割,切割成若干个大文档块,然后每个大文档块(chunk_size=1024)再被切分成4个块大小为512的子文档块,那么这些子文档块就是所谓的叶子节点,而子文档块所属的大文档块就是所谓的父节点,再比如定义切割的层次结构为[1024,512,128],这表示将文档按三层结构进行切割,那么顶层节点的块大小为1024,中间层的块大小为512,底层的叶子节点的块大小为128。而在检索时只拿叶子节点和问题进行匹配,当某个父节点下的多数叶子节点都与问题匹配上则将该父节点作为context返回给LLM,如下图所示:

接下来就是我们的实战环节,我们仍然使用上一篇博客中的使用的百度百科的文档,这次我们会使用LlamaIndex的AutoMergingRetriever对文档进行检索,最后我们仍然使用Trulens对检索结果进行评估。下面我们首先进行环境配置。

一、环境配置

我们首先需要安装如下python包

pip install llama_hub 
pip install llama_index
pip install trulens-eval
pip install trafilatura
pip install torch sentence-transformers

接下来我们需要做一些初始化的工作,比如导入openai的api_key:

import os
 
os.environ['OPENAI_API_KEY']="your_api_key"

二、加载数据

这里我们仍然使用前几篇博客中使用的数据即从百度百科的网页中抓取一篇关于恐龙的科普文章:

 下面我们使用LlamaIndex的网页爬虫工具TrafilaturaWebReader来爬取百度百科上的这篇关于恐龙的科普文章:

from llama_index.readers.web import TrafilaturaWebReader

url="https://baike.baidu.com/item/恐龙/139019"
documents = TrafilaturaWebReader().load_data([url])
documents

三、设置文档层次结构

在我们进行自动合并检索之前,我们需要创建一个文档切割器,它会按指定的文档的层次结构来切割文档,这里我们会将文档的层次结构设置为3层,文档切割器在切割文档时就会采样递归的切割方式对文档进行切割:

from llama_index.node_parser import HierarchicalNodeParser

node_parser = HierarchicalNodeParser.from_defaults(
    chunk_sizes=[2048, 512, 128]
)

这里我们设置了文档的层次结构为[2048, 512, 128],这就意味着每个叶子节点的大小(chunk_size)为128,需要说明的是这里的128是只文档的token数为128。下面我们就来使用这个文档切割器来切割之前下载的关于恐龙的科普文章:

nodes = node_parser.get_nodes_from_documents(documents)

len(nodes)

 这里我们看到原来的文档被切割成了337个文档块,接下来我们来看一下其中的某一个文档块的内容:

nodes[50]

 这里我们需要说明的是我们查看的是第50个文档块的内容,其中的NodeRelationship属性包含有SOURCE,PREVIOUS,NEXT,PARENT,CHILD,text 等与其相关的节点的索引信息(node_id),下面我们来解释一下这些相关节点属性的含义:

  • SOURCE: 指当前文档块源自于哪个文档(同PARENT)
  • PREVIOUS:指当前文档块的前一篇文档(与当前文档是兄弟关系)。
  • NEXT:指当前文档块的后一篇文档(与当前文档是兄弟关系)。
  • PARENT:指当前文档块所属的父文档(与当前文档是父子关系,同SOURCE)。
  • CHILD:指当前文档块的子文档(与当前文档是父子关系)。
  • text:当前文档块的内容。

下面我们可以单独查看叶子节点文档:

from llama_index.node_parser import get_leaf_nodes

leaf_nodes = get_leaf_nodes(nodes)
leaf_nodes[30]

这里我们查看了第30个叶子节点文档,由于是叶子节点,所以它不存在CHILD信息。同样也可以查看该叶子节点文档所属的父文档信息:

nodes_by_id = {node.node_id: node for node in nodes}

parent_node = nodes_by_id[leaf_nodes[30].parent_node.node_id]
parent_node

 这里我们看到第30个叶子节点的父文档中的text信息中包含了子节点的所有文本内容。

四、创建向量库索引

文档切割完成以后,接下来我们需要创建向量库索引,其步骤类似与我之前写的博客:句子-窗口检索,不熟悉的朋友可以看一下这篇博客。

from llama_index.llms import OpenAI
from llama_index import ServiceContext
from llama_index import VectorStoreIndex, StorageContext

#创建LLM
llm = OpenAI(model="gpt-3.5-turbo", temperature=0.1)

#创建ServiceContext
auto_merging_context = ServiceContext.from_defaults(
    llm=llm,
    embed_model="local:BAAI/bge-small-zh-v1.5",
    node_parser=node_parser,
)

#创建向量库索引
storage_context = StorageContext.from_defaults()
storage_context.docstore.add_documents(nodes)
automerging_index = VectorStoreIndex(
    leaf_nodes, 
    storage_context=storage_context, 
    service_context=auto_merging_context
)

#向量库持久化
automerging_index.storage_context.persist(persist_dir="./merging_index")

这里我们使用的LLM是Openai的gpt-3.5-turbo,embedding模型为bge-small-zh-v1.5,最后我们做了向量库的持久化操作即将向量库保存在本地,这样做的好处是下次使用时不需要重新去下载数据和创建向量库索引,而只需读取本地保存的向量库索引就可以了。下面我们就来测试一下读取刚才保存在本地的向量库索引(这个步骤是可选的):

import os
from llama_index import VectorStoreIndex, StorageContext, load_index_from_storage
from llama_index import load_index_from_storage

if not os.path.exists("./merging_index"):
    storage_context = StorageContext.from_defaults()
    storage_context.docstore.add_documents(nodes)

    automerging_index = VectorStoreIndex(
            leaf_nodes,
            storage_context=storage_context,
            service_context=auto_merging_context
        )

    automerging_index.storage_context.persist(persist_dir="./merging_index")
else:
    automerging_index = load_index_from_storage(
        StorageContext.from_defaults(persist_dir="./merging_index"),
        service_context=auto_merging_context
    )

五、定义和执行检索器

创建了向量库索引以后,我们就需要创建检索器,检索引擎,然后通过该检索引擎对用户问题进行检索了:

from llama_index.indices.postprocessor import SentenceTransformerRerank
from llama_index.retrievers import AutoMergingRetriever
from llama_index.query_engine import RetrieverQueryEngine

base_retriever = automerging_index.as_retriever(
    similarity_top_k=12
)

retriever = AutoMergingRetriever(
    base_retriever, 
    automerging_index.storage_context, 
    verbose=True
)

rerank = SentenceTransformerRerank(top_n=6, model="BAAI/bge-reranker-base")

auto_merging_engine = RetrieverQueryEngine.from_args(
    retriever, node_postprocessors=[rerank]
)

这里我们创建了一个自动合并检索器automerging_retriever,它有一个输入参数similarity_top_k,我们将其设置为12,这意味着检索器每次在检索时会返回12个相关文档(context), 同时我们还设置了一个rerank模型bge-reranker-base以及该模型的参数top_n为6,rerank模型的作用是将最检索到的12个context重新排序后获取最相关的6个context。接下来我们就来通过该检索引擎来检索用户问题:

auto_merging_response = auto_merging_engine.query(
    "恐龙是冷血动物吗?"
)

 这里由于我们在创建AutoMergingRetriever时设置了verbose=True因此检索器在检索相关文档时会显示检索过程的中间结果,从这些中间结果中我们看到其中有一个父节点中的3个叶子节点被检索到了,因为一个父节点包含最多4个叶子节点(由文档层次结构确定),那么如果父节点中有3个叶子节点被检索到,那么该父节点将会作为context被返回给llm,而当只有1个叶子节点被检索到时,该父节点将不会被返回给llm。

下面我们看看LLM给出的最终答案:

from llama_index.response.notebook_utils import display_response

display_response(auto_merging_response)

这里我们提出了一个关于“恐龙为什么会灭绝?”问题,我们看到LLM给出了详细的解答。

 下面我们给出完整的程序:

import os

from llama_index import (
    ServiceContext,
    StorageContext,
    VectorStoreIndex,
    load_index_from_storage,
)
from llama_index.node_parser import HierarchicalNodeParser
from llama_index.node_parser import get_leaf_nodes
from llama_index import StorageContext, load_index_from_storage
from llama_index.retrievers import AutoMergingRetriever
from llama_index.indices.postprocessor import SentenceTransformerRerank
from llama_index.query_engine import RetrieverQueryEngine
from llama_index.llms import OpenAI


def build_automerging_index(
    documents,
    llm,
    embed_model="local:BAAI/bge-small-zh-v1.5",
    save_dir="merging_index",
    chunk_sizes=None,
):
    chunk_sizes = chunk_sizes or [2048, 512, 128]
    node_parser = HierarchicalNodeParser.from_defaults(chunk_sizes=chunk_sizes)
    nodes = node_parser.get_nodes_from_documents(documents)
    leaf_nodes = get_leaf_nodes(nodes)
    merging_context = ServiceContext.from_defaults(
        llm=llm,
        embed_model=embed_model,
    )
    storage_context = StorageContext.from_defaults()
    storage_context.docstore.add_documents(nodes)

    if not os.path.exists(save_dir):
        automerging_index = VectorStoreIndex(
            leaf_nodes, storage_context=storage_context, service_context=merging_context
        )
        automerging_index.storage_context.persist(persist_dir=save_dir)
    else:
        automerging_index = load_index_from_storage(
            StorageContext.from_defaults(persist_dir=save_dir),
            service_context=merging_context,
        )
    return automerging_index


def get_automerging_query_engine(
    automerging_index,
    similarity_top_k=12,
    rerank_top_n=6,
):
    base_retriever = automerging_index.as_retriever(similarity_top_k=similarity_top_k)
    retriever = AutoMergingRetriever(
        base_retriever, automerging_index.storage_context, verbose=True
    )
    rerank = SentenceTransformerRerank(
        top_n=rerank_top_n, model="BAAI/bge-reranker-base"
    )
    auto_merging_engine = RetrieverQueryEngine.from_args(
        retriever, node_postprocessors=[rerank]
    )
    return auto_merging_engine

index = build_automerging_index(
    [document],
    llm=OpenAI(model="gpt-3.5-turbo", temperature=0.1),
    save_dir="./merging_index",
)

query_engine = get_automerging_query_engine(index, similarity_top_k=6)

auto_merging_response = auto_merging_engine.query(
    "恐龙是冷血动物吗?"
)

display_response(auto_merging_response)

六、评估解释结果

在对自动合并检索进行评估时,我们需要先设置一组问题,然后我们让检索器来回答这组问题并生成答案,最后由评估器通过收集到的问题,答案,上下文(context)来综合评估LLM给出答案的质量,这里我们仍然使用TruLens三元组的评估指标(即Context Relevance,Groundedness和Answer Relevance的分数)来量化评估的效果,对此TruLens评估不熟悉朋友可以查看我之前写的TruLens 评估-扩大和加速LLM应用程序评估 和 评估句子-窗口检索 这两篇博客中关于TruLens评估的介绍。下面我们做一下评估前的初始化工作:

from trulens_eval import Tru
from trulens_eval import Feedback,TruLlama
from trulens_eval import OpenAI as fOpenAI
from trulens_eval.feedback import Groundedness
import numpy as np


import nest_asyncio

#初始化评估数据库
Tru().reset_database()  

#设置线程的并发执行
nest_asyncio.apply()

接下来我们需要定义一组用来评估检索效果的问题:

#定义问题
eval_questions = [
                 "恐龙分哪几类?",
                 "体型最大的是哪种恐龙?",
                 "恐龙是怎么繁殖的?",
                 "恐龙是冷血动物吗?",
                 "恐龙为什么会灭绝? 什么时候灭绝的?",
                ]

然后会创建一个评估记录器函数,其中包含了选用的评估指标,最后我们会创建一个执行评估的函数:

#创建评估器对象
tru = Tru()
 
#定义评估记录器
def get_prebuilt_trulens_recorder(query_engine, app_id):
    openai = fOpenAI()
 
    qa_relevance = (
        Feedback(openai.relevance_with_cot_reasons, name="Answer Relevance")
        .on_input_output()
    )
 
    qs_relevance = (
        Feedback(openai.relevance_with_cot_reasons, name = "Context Relevance")
        .on_input()
        .on(TruLlama.select_source_nodes().node.text)
        .aggregate(np.mean)
    )
 
    grounded = Groundedness(groundedness_provider=openai)
 
    groundedness = (
        Feedback(grounded.groundedness_measure_with_cot_reasons, name="Groundedness")
            .on(TruLlama.select_source_nodes().node.text)
            .on_output()
            .aggregate(grounded.grounded_statements_aggregator)
    )
 
    feedbacks = [qa_relevance, qs_relevance, groundedness]
    tru_recorder = TruLlama(
        query_engine,
        app_id=app_id,
        feedbacks=feedbacks
    )
    return tru_recorder
 
#定义执行评估函数
def run_evals(eval_questions, tru_recorder, query_engine):
    for question in eval_questions:
        with tru_recorder as recording:
            response = query_engine.query(question)
            

二层结构评估

在完成了上述评估前的准备工作以后,接下来我们需要定义向量库索引,和创建检索引擎,最后执行检索,这里需要说明的是在本轮评估时我们采样的文档切割的层次结构为2层结构[2048,512]即叶子节点的块大小(chunk_size)为512,父节点的块大小为2048。

#创建向量库索引
auto_merging_index_0 = build_automerging_index(
    documents,
    llm=OpenAI(model="gpt-3.5-turbo", temperature=0.1),
    embed_model="local:BAAI/bge-small-zh-v1.5",
    save_dir="merging_index_0",
    chunk_sizes=[2048,512], 
)
#创建检索引擎
auto_merging_engine_0 = get_automerging_query_engine(
    auto_merging_index_0,
    similarity_top_k=12,
    rerank_top_n=6,
)
#创建记录器
tru_recorder = get_prebuilt_trulens_recorder(
    auto_merging_engine_0,
    app_id ='app_0'
)

#执行评估
run_evals(eval_questions, tru_recorder, auto_merging_engine_0)

当执行完评估完成以后,我们可以查看一下评估结果:

Tru().get_leaderboard(app_ids=[])

这里我们从本轮评估的结果中看到了三元组指标Context Relevance,Groundedness和Answer Relevance的分数,以及整个评估的耗时latency为15秒和评估的成本0.005433美刀,下面我们查看TruLens提供的基于streamlit的web app 界面:

Tru().run_dashboard()

 三层结构评估

接下来我们将文档分割的层级结构设置为3层[2048,512,128], 这样我们的叶子节点的块大小将为128,而叶子节点的父文档的块大小则为512。

auto_merging_index_1 = build_automerging_index(
    documents,
    llm=OpenAI(model="gpt-3.5-turbo", temperature=0.1),
    embed_model="local:BAAI/bge-small-en-v1.5",
    save_dir="merging_index_1",
    chunk_sizes=[2048,512,128],
)

auto_merging_engine_1 = get_automerging_query_engine(
    auto_merging_index_1,
    similarity_top_k=12,
    rerank_top_n=6,
)

tru_recorder = get_prebuilt_trulens_recorder(
    auto_merging_engine_1,
    app_id ='app_1'
)

run_evals(eval_questions, tru_recorder, auto_merging_engine_1)

Tru().get_leaderboard(app_ids=[])

这里我们观察到当我们的文档切割方式采样了3层结构以后,三元组指标中Groundedness和Answer Relevance的分数都达到的最高值1,而Context Relevance略有下降,这是由于我们采用的是三层文档分割方式,此时叶子节点的父节点的块大小为512,而在之前二层结构切割文档时叶子节点的父节点的块大小为2048,因为我们每次只返回检索到的叶子节点的父节点文档,所以块大小为512的父文档的信息量要比块大小为2048的父文档的信息量要少,所以造成了Context Relevance的分数略有所下降,但是总成本total_cost为0.001654美刀,要比之前下降了一些,这是因为返回的父文档的token数只有之前的1/4,因此评估成本也相应的降下来了。下面我们查看TruLens提供的基于streamlit的web app 界面:

Tru().run_dashboard()

关于自动合并检索评估的方法总结和补充说明: 

  •  使用不同的文档层次结构参数进行迭代(级别数、子级数)和不同的块大小
  • 使用 RAG三元组评估应用程序版本
  • 跟踪实验以选择最佳的文档分割的层次结构参数
  • 找到关于最适合某些文档类型的超参数(文档层次结构参数)的直觉
  • 自动合并检索是对句子-窗口检索的补充

七、参考资料

Auto Merging Retriever - LlamaIndex 🦙 0.9.33

New Features in Jina v0.5 You Should Know About · Han Xiao Tech Blog - Neural Search & AI Engineering

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

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

相关文章

北斗卫星:助力社区矫正人员追踪与管理的科技突破

北斗卫星:助力社区矫正人员追踪与管理的科技突破 社区矫正人员是一个重要的社会群体,他们的安全和管理对于社会的和谐稳定至关重要。随着技术的飞跃发展,北斗卫星系统作为我国自主研发的卫星导航系统,正逐渐在社区矫正工作中发挥…

UE5 播放rtsp监控视频

1. 插件下载 https://github.com/inveta/InVideo https://github.com/inveta/InVideo/releases https://download.csdn.net/download/qq_17523181/88760489?spm1001.2014.3001.5501 插件目前支持5.1 / 5.0 2. 建立C UE5项目 重要:此插件支持C项目,不然不…

Windows Server搭建DNS服务器

服务器规划 DNS服务器IP为:192.168.2.82 需要自定义域名解析 192.168.2.82 dns.zhangsan.com 192.168.2.181 www.zhangsan.com 192.168.2.182 test1.zhangsan.com 192.168.2.183 test2.zhangsan.com 0. 服务器系统信息 1. 服务器初始化 1.1 查询IP 在命令行窗口中…

【React基础】– JSX语法

文章目录 认识JSX为什么React选择了JSXJSX的使用 React事件绑定this的绑定问题事件参数传递 React条件渲染React列表渲染列表中的key JSX的本质createElement源码Babel官网查看直接编写jsx代码 虚拟DOM的创建过程jsx – 虚拟DOM – 真实DOM声明式编程 阶段案例练习 认识JSX ◼ …

【重学C语言】四、常量、变量和基本数据类型

【重学C语言】四、常量、变量和基本数据类型 1. 常量和变量1.1 常量1.1.1 直接常量1.1.1.1 整数常量1.1.1.2 浮点常量1.1.1.3 字符常量1.1.1.4字符串常量 1.1.2符号常量 1.2 标识符1.3 变量1.3.1 变量的定义1.3.2 左值(Lvalues)和右值(Rvalue…

a-range-picker获取开始和结束时间

效果图 代码块 <a-range-picker change"onChangeRangeDate" format"YYYY-MM-DD"/>onChangeRangeDate(value,dateString){this.startDatedateString[0]this.endDatedateString[1]}

抓包工具Fiddler的下载、安装、配置、基本使用

文章目录 前言一、Fiddler下载二、Fiddler安装三、打开Fiddler四、Fiddler显示菜单栏及菜单栏功能基本介绍五、Fiddler的作用六、Fiddler的工作原理七、Fiddler基本功能使用1.导包2.规则设置Rules&#xff1a; 八、Fiddler设置抓取HTTPS的包九、抓取APP包必须设置十、Fiddler过…

谷达冠楠科技:抖音开网店新手小白可以卖的产品

随着互联网的发展&#xff0c;越来越多的人选择在网上开设自己的店铺。而抖音作为目前最火的短视频平台&#xff0c;也提供了开店的功能。那么&#xff0c;对于新手小白来说&#xff0c;抖音开网店可以卖哪些产品呢? 我们可以考虑的是服装类商品。抖音上有很多时尚博主&#x…

极致画质与流畅播放的完美结合,只在ProVideoPlayer for Mac!

ProVideoPlayer for Mac 是一款功能强大的专业级视频播放软件&#xff0c;旨在提供出色的用户体验和无与伦比的功能。以下是它的一些主要功能介绍&#xff1a; 多格式兼容&#xff1a;ProVideoPlayer for Mac 支持广泛的视频格式&#xff0c;包括常见的MP4、AVI、MOV&#xff0…

鸿蒙开发(五)鸿蒙UI开发概览

从用户角度来讲&#xff0c;一个软件拥有好看的UI&#xff0c;那是锦上添花的事情。再精确的算法&#xff0c;再厉害的策略&#xff0c;最终都得通过UI展现给用户并且跟用户交互。那么&#xff0c;本篇一起学习下鸿蒙开发UI基础知识&#xff0c;认识下各种基本控件以及使用方式…

基于Java图书商城系统设计与实现(源码+部署文档)

博主介绍&#xff1a; ✌至今服务客户已经1000、专注于Java技术领域、项目定制、技术答疑、开发工具、毕业项目实战 ✌ &#x1f345; 文末获取源码联系 &#x1f345; &#x1f447;&#x1f3fb; 精彩专栏 推荐订阅 &#x1f447;&#x1f3fb; 不然下次找不到 Java项目精品实…

三星Galaxy S24 系列了发布会预热新品:Galaxy Ring 智能戒指亮相

在三星 Galaxy S24 系列发布会上&#xff0c;他们不仅带来了新款手机&#xff0c;还意外地推出了一款智能指环 ——Galaxy Ring&#xff01;没错&#xff0c;就是戴在手指上的那种智能设备&#xff01; 在发布会的尾声&#xff0c;三星放出了一段简短的预告片&#xff0c;让我…

美摄视频SDK的HDR格式编辑方案

在当今的视觉媒体时代&#xff0c;高动态范围&#xff08;HDR&#xff09;技术已成为高质量视频内容的标配。为了满足企业对高效、高质量视频处理的需求&#xff0c;美摄科技推出了业界领先的视频SDK&#xff0c;全面支持多种HDR标准的图像视频进行处理。 一、核心优势 HDR全…

【Docker】安装nacos以及实现负载均衡

&#x1f973;&#x1f973;Welcome 的Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于Docker的相关操作吧 目录 &#x1f973;&#x1f973;Welcome 的Huihuis Code World ! !&#x1f973;&#x1f973; 前言 一.nacos单个部署 1.镜像拉取 …

Java实现厦门旅游电子商务预订系统 JAVA+Vue+SpringBoot+MySQL

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 景点类型模块2.2 景点档案模块2.3 酒店管理模块2.4 美食管理模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 学生表3.2.2 学生表3.2.3 学生表3.2.4 学生表 四、系统展示五、核心代码5.1 新增景点类型5.2 查询推荐的…

2024-01-18 在Android Studio中,可以通过修改build.gradle文件(位于你的应用模块目录下)来自定义生成的APK名称

一、在Android Studio中&#xff0c;可以通过修改build.gradle文件&#xff08;位于你的应用模块目录下&#xff09;来自定义生成的APK名称&#xff0c;在build.gradle里面增加下面的代码 applicationVariants.all { variant ->variant.outputs.all {outputFileName "…

Segment Anything:SAM系列模型总结

Segment Anything | Meta AIhttps://segment-anything.com/ SAM https://arxiv.org/pdf/2304.02643.pdf 新的图像分割任务:这样的任务需要实现零样本泛化。新的模型&#xff1a;Segment Anthing Model。目前分为vit_b&#xff0c;vit_l&#xff0c;vit_h新的数据集&#xff…

使用人工智能助手 Github Copilot 进行编程 01

本章涵盖了 AI 助⼿如何改变新程序员的学习⽅式为什么编程永远不会再⼀样了AI 助⼿如 Copilot 的⼯作原理Copilot 如何解决⼊⻔级编程问题AI 辅助编程的潜在危险 在本章中&#xff0c;我们将讨论人类如何与计算机进行交流。我们将向您介绍您的 AI 助手 GitHub Copilot&#x…

Git 基本命令与操作流

记录 Git 中的基本命令和创建仓库、提交文件、删除文件等方面的操作 Git 基本命令 git status&#xff1a;查看状态 nothing to commit, working directory clean&#xff1a;所有已跟踪文件在上次提交后都未被更改过&#xff0c;或者说当前目录下没有出现任何处于未跟踪状态…

一篇文章带你彻底了解flex布局

哈喽&#xff0c;大家好呀&#xff0c;我是前端理想哥&#xff0c;今天我们来聊聊 flex 布局。 好&#xff0c;主角登场。 CSS 弹性盒子模型( Flexible Box 或者 Flexbox ) 先来看看它的定义&#xff1a;弹性布局是指通过调整其内元素的宽高&#xff0c;从而在任何显示设备上…