LLM本地知识库问答系统(一):使用LangChain和LlamaIndex从零构建PDF聊天机器人指南

       随着大型语言模型(LLM)(如ChatGPT和GPT-4)的兴起,现在比以往任何时候都更容易构建比普通熊更智能的智能聊天机器人,并且可以浏览堆积如山的文档,为您的输入提供准确的响应。

       在本系列中,我们将探索如何使用pre-trained的LLM创建一个聊天机器人,该聊天机器人可以分析、总结PDF文档并回答问题,使其成为企业和个人都非常有用的工具。无论您是想构建个人助理、定制聊天机器人还是自动文档分析系统,本系列都将为您提供构建自己的LLM聊天机器人所需的知识。所以,让我们用LangChain和LlamaIndex深入LLM和聊天机器人的世界吧!

创建什么?

       使用ChatGPT作为助手来帮助用户基于多个文档进行问答系统搭建的想法是非常酷。起初,我们的想法是用特定的数据对模型进行微调,以实现这一目标,但这可能成本高昂,并且需要庞大的数据集。此外,对模型进行微调只能教会它一项新技能,而不能提供有关文档的完整信息。

      另一种方法是使用提示工程在(多)文档QA的提示中提供上下文。然而,GPT模型的注意力范围有限,将上下文传递给API也可能很昂贵,尤其是在处理大量客户反馈电子邮件和产品文档时。

那么如何创建呢?

以下是实现这些目标的具体步骤:

  1. 首先加载文档(PDF、HTML、文本、数据库等);
  2. 然后将数据分割成块,并对这些块建立embedding索引,这样方便使用向量检索工具进行语义搜索;
  3. 对于每个问题,通过搜索索引和embedding数据来获取与问题相关的信息;
  4. 将问题和相关数据输入到LLM模型中。在这个系列中使用OpenAI的LLM;

       实现上述过程主要的两个框架,分别是:Langchain(https://python.langchain.com/en/latest/)和LLamaIndex(https://gpt-index.readthedocs.io/en/latest/)

我们如何开始

下面是使用Langchain和ChatGPT实现PDF问答系统的大致框架:

      在本文,不会详细介绍Langchain或LLamaIndex具体原理和实现细节,后面会专门介绍。本文主要介绍如下内容:

  • 基于Langchain的生成式问答
  • LLamaIndex生成式问答
  • 奖金部分。

准备工作

     首先我们需要在OPenAI官网获取API秘钥,具体步骤是:转到https://platform.openai.com,登录或注册新帐户→ 点击您的个人资料→ 查看API密钥并创建新的密钥,如下图所示:

Note:实际上,我们可以使用其他LLM模型。

       下面准备安装相关的python包,需要保证Python>=3.7来进行操作,然后创建一个虚拟环境并安装以下Python库:

## to create virtual environment$ python3 -m venv llm_app_env## on MacOS or Linux$ source llm_app_env/bin/activate## on Window$ llm_app_env\Scripts\activate.bat## then install the following libraries.openai[embeddings]==0.27.6langchain==0.0.155pypdf==3.8.1tiktoken==0.3.3faiss-cpu==1.7.4unstructured==0.6.2chromadb==0.3.21llama-index==0.6.1jupyterlab

Langchain介绍

       LangChain是一个强大的开源工具,可以轻松地与大型语言模型交互并构建应用程序。将其视为一个中间人,将您的应用程序连接到广泛的LLM提供商,如OpenAI、Cohere、Huggingface、Azure OpenAI等。

       然而,LangChain不仅仅是一个访问预训练语言模型的工具,它还提供了许多有用的特性和功能,允许您构建自定义应用程序和工具。例如:

  • 使用自己的文档进行问答和文本摘要
  • 处理内存和具有有限令牌问题的长文档。
  • 与OpenAI ChatGPT Retriever插件的出色集成
  • 多个链来处理您定义的问题,或者使用Agent将其提升。
  • 还有更多。

       Langchain是一个伟大的框架,它使人工智能应用程序的创建能力现在掌握在您手中。更令人惊讶的是,它是开源的,所以你知道它掌握在优秀社区的手中。

下面使用Langchain来搭建一个问答系统:

设置OpenAI API密钥

import loggingimport sysimport osos.environ["OPENAI_API_KEY"] = "<YOUR_OPENAI_API_KEY>"

加载并拆分数据

## load the PDF using pypdffrom langchain.document_loaders import PyPDFLoaderfrom langchain.text_splitter import RecursiveCharacterTextSplitter# load the dataloader = PyPDFLoader('../notebooks/documents/Apple-Financial-Report-Q1-2022.pdf')# the 10k financial report are huge, we will need to split the doc into multiple chunk.# This text splitter is the recommended one for generic text. It is parameterized by a list of characters. # It tries to split on them in order until the chunks are small enough.text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=0)data = loader.load()texts = text_splitter.split_documents(data)# view the first chunktexts[0]

简单问答

       我们将使用OpenAI作为LLM提供者,因此使用OpenAI Embedding,但请注意,OpenAI Embedding API使用的是“text-davinci-003”模型(定价参考:https://openai.com/pricing)

       接下来,我们将导入Chroma,Chroma是嵌入数据库,不像传统的SQL数据库,也不像你通常使用的NoSQL数据库。它嵌入了数据库,使构建LLM应用程序变得容易。

通过Chroma官方网站

       我们的文档以文本的形式表示,因此很难根据问题找到相关信息。假设你需要在1000页中找到苹果上一季度的收入,并将收入与前几年进行比较。这可能需要多大的挑战性和耗时?因此,为了让我们的搜索更容易,我们首先需要以数字格式转换或表示单词或短语,这些单词或短语可以用作机器学习模型的输入。换句话说,帮助机器理解文本。embeddings将每个单词或短语映射到实数向量,通常具有数百个维度,使得相似的单词或短语被映射到嵌入空间中的相似向量。

       使用embeddings的主要优点之一是,它们可以捕捉单词或短语之间的语义和句法关系。例如,在嵌入空间中,“国王”和“王后”的向量比“苹果”的向量更接近,因为它们在语义上与王室头衔相关。

       因此,嵌入数据库正是这样做的。它将把所有embeddings数据存储在数据库中,然后给我们提供非常多的索引,使我们能够执行类似数据检索的操作,并以可扩展的风格进行操作。如果你需要得到之前关于寻找苹果上季度收入的问题的答案,我们首先需要在嵌入Chroma等数据库的基础上进行相似性搜索或语义搜索,以提取相关信息,并将这些信息提供给LLM模型来获得答案。

       听起来太复杂了!这就是Langchain拯救我们的地方,所有的艰苦工作都将在后台完成。Just do it!

# import Chroma and OpenAIEmbeddingsfrom langchain.vectorstores import Chromafrom langchain.embeddings.openai import OpenAIEmbeddings# initialize OpenAIEmbeddingembeddings = OpenAIEmbeddings(model='text-embedding-ada-002')# use Chroma to create in-memory embedding database from the docdocsearch = Chroma.from_documents(texts, embeddings,  metadatas=[{"source": str(i)} for i in range(len(texts))])## perform search based on the questionquery = "What is the operating income?"docs = docsearch.similarity_search(query)

       您可以看到,我们能够执行相似性搜索,从嵌入数据库中获取相关信息。

       现在,我们将使用Langchain的主要组件之一Chain将LLM提供程序合并到我们的代码中。请记住,本文的目的是建立问答机器人。因此,只需按照步骤进行操作,如果你很好奇,迫不及待地想了解更多细节,请随时访问Langchain的官方网站。瓦尔哈拉在等着你!!!!

Langchain提供了四种预先构建的问答Chain,具体如下:

  • 问答:load_qa_chain
  • 有来源问答:load_qa_with_sources_chain
  • 检索问题答案:RetrievalQA
  • 资源检索问答:RetrievalQAWithSourcesChain

      它们非常相似,RetrievalQA和RetrievalQAWithSourcesChain分别使用load_qa_chain和load_qa_with_sources_chain,唯一的区别是前两者将把所有嵌入都馈送到LLM中,而后两者只向LLM提供相关信息。我们可以使用前两个来首先提取相关信息,并仅将该信息提供给LLM。此外,前两个比后两个给了我们更多的灵活性。

下面的代码将演示我们是如何做到这一点的。

## importing necessary frameworkfrom langchain.chains.question_answering import load_qa_chainfrom langchain.chains.qa_with_sources import load_qa_with_sources_chainfrom langchain.chains import RetrievalQAfrom langchain.chains import RetrievalQAWithSourcesChainfrom langchain.chat_models import ChatOpenAI

现在我们将尝试4种不同的问答链

1.load_qa_chain

## use LLM to get answeringchain = load_qa_chain(ChatOpenAI(temperature=0.2,model_name='gpt-3.5-turbo'),                       chain_type="stuff")query = "What is the operating income?"chain.run(input_documents=docs, question=query)

2.load_qa_with_sources_chain

chain = load_qa_with_sources_chain(ChatOpenAI(temperature=0.2,model_name='gpt-3.5-turbo'),                                    chain_type="stuff")query = "What is the operating income?"chain({"input_documents": docs, "question": query}, return_only_outputs=True)

3.RetrievalQA

qa=RetrievalQA.from_chain_type(llm=ChatOpenAI(temperature=0.2,model_name='gpt-3.5-turbo'), chain_type="stuff",                                                 retriever=docsearch.as_retriever())query = "What is the operating income?"qa.run(query)

4.RetrievalQAWithSourcesChain

chain=RetrievalQAWithSourcesChain.from_chain_type(ChatOpenAI(temperature=0.2,model_name='gpt-3.5-turbo'), chain_type="stuff",                                                     retriever=docsearch.as_retriever())chain({"question": "What is the operating income?"}, return_only_outputs=True)

       上面的大部分代码都是非常基本的。我们只想在深入研究框架能提供什么之前完成这项工作。在此之前,让我们转到另一个可以与Langchain结合使用的框架,它将为您提供更多的能力来创建更好的LLM应用程序。

LLamaIndex介绍

       我首先介绍了Langchain,如果你花一些时间浏览它的官方文件,你可能会想“哇,没有什么好的东西可以超越这一点”。

       好吧,我的朋友们,有一个完整的SaaS行业建立在AWS之上,只是为了让您更好、更容易地使用AWS服务。其他LLM框架或LLM模型之间的竞争也是如此。我们生活在一个今天好的东西明天可能会过时的世界里。我个人认为Langchain将有一个非常光明的未来,并将成为用于构建LLM应用程序的核心技术。LLamIndex甚至让我们的工作变得更容易,它还通过处理一些痛苦的众所周知的问题和现有方法的局限性引入了自己的优势,这些问题和局限性将花费您的时间和手动操作,例如:

  • 文本块缺少全局上下文。通常,这个问题需要特定区块中索引之外的上下文。
  • 仔细调整前k/相似性得分阈值。如果值太小,就会错过上下文。让价值变得太大,成本/延迟可能会随着不相关的上下文而增加。
  • Embeddings并不总是为问题选择最相关的上下文。Embeddings本质上是在文本和上下文之间分别确定的。

       LLamaIndex(GPT索引)有自己的机制来处理这些限制。同样,这个博客的目的是完成这项工作。我不会详细介绍LLamaIndex是如何工作的(可以在官方文件上找到)。

那么LLM是什么

       一张由Jerry Liu抄写的羊皮纸,他在羊皮纸上公布了LlamaIndex,这是一个利用GPT的力量,利用询问者提供的知识,形成对询问的回复的门户网站。

       简而言之,LlamaIndex是通过以下步骤将LLM连接到用户来响应查询的另一种方式(类似于Langchain的方式):

  1. 加载文档(手动或通过数据加载程序)

  2. 将文档解析为节点

  3. 构造索引(从节点或文档)

  4. [可选,高级]在其他指数之上构建指数

  5. 查询索引

        简单来说,LlamaIndex将数据加载到文档对象中,并将其转换为索引。当您输入查询时,索引会将其发送到GPT提示符以生成响应,默认情况下使用OpenAI的text-davinci-003模型。尽管这个过程看起来很复杂,但只要几行代码就可以执行,您很快就会了解到这一点。

       您很快就会看到LLamaIndex是多么容易使用,因为它已经完成了所有的艰苦工作。你的工作只是阅读它的官方文件,学习不同类型的索引,然后分析你的应用程序需求,看看什么最适合你。当然,你的应用程序中可能需要越来越多复杂的东西,LLamaIndex的高级API可能不足以处理此类情况。这就是LLamaIndex可以与Langchain等其他工具集成以加快开发过程的便利之处。

让我们从设置简单索引和加载文档开始。

import loggingimport sys## setup your OpenAI Keyimport osos.environ["OPENAI_API_KEY"] = "<YOUR_OPENAI_API_KEY>"# enable logs to see what happen underneathlogging.basicConfig(stream=sys.stdout, level=logging.DEBUG)logging.getLogger().addHandler(logging.StreamHandler(stream=sys.stdout))

LlamaIndex的核心是指数,有多种类型的指数。

  • 列表索引
  • 矢量存储索引
  • 树索引
  • 关键字表索引
  • 图形索引
  • SQL索引。

       每个索引都有其独特的用途,具有不同的用途。好处是,您可以将索引堆叠在其他索引之上,这样做将使您的应用程序更强大,能够理解您的文档上下文和应用程序需求。

第一步是加载文档

from llama_index import GPTVectorStoreIndexfrom llama_index import download_loader# we will use this UnstructuredReader to read PDF fileUnstructuredReader = download_loader('UnstructuredReader', refresh_cache=True)loader = UnstructuredReader()# load the datadata = loader.load_data(f'../notebooks/documents/_10-Q-Q1-2022-(As-Filed).pdf', split_documents=False)

Document表示数据源的轻量级容器。可以选择下面两步骤之一:

  1. 将Document对象直接输入索引

  2. 首先,将文档转换为Node对象

       同样,本系列的目的是帮助您尽快构建第一个应用程序,因此我将直接讨论索引构建。我将在未来的一篇文章中介绍LLamaIndex的所有方面。

索引构建与查询

       我们现在可以在这些Document对象上建立一个索引。最简单的高级抽象是在索引初始化期间加载Document对象。

index = GPTVectorStoreIndex.from_documents(data)query_engine = index.as_query_engine()response = query_engine.query("What is the operating income?")print(response)

      根据您使用的索引,LlamaIndex可能会进行LLM调用以构建索引。GPTVvectorStoreIndex不会调用LLM,但GPTTreeStoreIndex会调用。

自定义LLM

      默认情况下,LlamaIndex使用OpenAI的text-davinci-003模型。在构造索引时,您可以选择使用另一个LLM。

from llama_index import LLMPredictor, PromptHelper, ServiceContextfrom langchain.chat_models import ChatOpenAI# define LLMllm_predictor = LLMPredictor(llm=ChatOpenAI(temperature=0.2,model_name='gpt-3.5-turbo'))# define prompt helper# set maximum input sizemax_input_size = 4096# set number of output tokensnum_output = 256# set maximum chunk overlapmax_chunk_overlap = 20prompt_helper = PromptHelper(max_input_size, num_output, max_chunk_overlap)service_context = ServiceContext.from_defaults(llm_predictor=llm_predictor, prompt_helper=prompt_helper)index = GPTVectorStoreIndex.from_documents(    documents,     service_context=service_context)query_engine = index.as_query_engine()response = query_engine.query("What is the operating income?")print(response)

       在短短几行代码中,我们就能够构建一个LLM应用程序,可以进行基本的问答。

       对于具有机器学习工程师或数据科学背景的人来说,这是相当简单明了的,但我相信对于一些新手来说,有时会觉得很困惑。我理解这一点,但很难在一篇帖子中解释所有内容。这篇文章的目的只是让你体验一下现在构建这样一个令人惊叹的LLM应用程序是多么容易。你现在可能有很多问题,甚至可能几行代码都不懂,但这没关系。

       您将很快收集组件的所有知识和方面,以构建自己的LLM应用程序。你可以等到我的下一篇文章,因为我将在下一篇中介绍LlamaIndex,或者如果你足够好奇,请通过阅读官方文件来做好准备。

       在此之前,我希望这篇文章能够帮助您扩展编码知识,并为LLM提供有价值的见解。记得保持好奇心,继续探索人工智能的广阔世界。

       祝贺你走到这一步!作为对您努力的奖励,这里有一段代码,您可以使用它与文档聊天

# do importsfrom langchain.agents import Toolfrom langchain.chains.conversation.memory import ConversationBufferMemoryfrom langchain.chat_models import ChatOpenAIfrom langchain.agents import initialize_agentfrom llama_index.langchain_helpers.agents import LlamaToolkit, create_llama_chat_agent, IndexToolConfigquery_engine = index.as_query_engine()tool_config = IndexToolConfig(    query_engine=query_engine,     name=f"Financial Report",    description=f"useful for when you want to answer queries about the Apple financial report",    tool_kwargs={"return_direct": True})toolkit = LlamaToolkit(    index_configs=[tool_config])memory = ConversationBufferMemory(memory_key="chat_history")llm=ChatOpenAI(temperature=0.2,model_name='gpt-3.5-turbo')agent_chain = create_llama_chat_agent(    toolkit,    llm,    memory=memory,    verbose=True)while True:    text_input = input("User: ")    response = agent_chain.run(input=text_input)    print(f'Agent: {response}')

YouTube视频结果展示地址:https://youtu.be/FuKFjNNbSVM

参考文献:

[1] https://langchain.readthedocs.io/en/latest/index.html(LangChain docs)

[2] https://langchain.readthedocs.io/en/latest/modules/memory.html#memory(LangChain Prompt Memory module)

[3] https://github.com/hwchase17/langchain(LangChain Repo)

[4] https://gpt-index.readthedocs.io/en/latest/index.html(LlamaIndex docs)

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

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

相关文章

《Linux从练气到飞升》No.18 进程终止

&#x1f57a;作者&#xff1a; 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux菜鸟刷题集 &#x1f618;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &#x1f3c7;码字不易&#xff0c;你的&#x1f44d;点赞&#x1f64c;收藏❤️关注对我真的…

sql:SQL优化知识点记录(三)

&#xff08;1&#xff09;explain之select_type和table介绍 简单的查询类型是&#xff1a;simple 外层 primary&#xff0c;括号里subquery 用到了临时表&#xff1a;derived &#xff08;2&#xff09;explain之select_type介绍 trpe反映的结果与我们sql是否优化过&#xff…

SpringCloud学习笔记(一)_快速入门

SpringCloud简介 Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具&#xff08;例如配置管理&#xff0c;服务发现&#xff0c;断路器&#xff0c;智能路由&#xff0c;微代理&#xff0c;控制总线&#xff09;。分布式系统的协调导致了样板模式, 使用Spr…

分布式事务(7):SpringCloud2.0整合LCN

目前LCN版本已经升级为4.0了,但是官方没有SpringCloud2.0的demo案例。 因为LCN本身是开源的,有些大神对LCN框架源码做修改,可以支持SpringCloud2.0版本。 下载地址:https://download.csdn.net/download/u013938578/88251904 1 下载LCN服务端源码 https://download.csdn.…

【OpenCV • c++】图像对比度调整 | 图像亮度调整

&#x1f680; 个人简介&#xff1a;CSDN「博客新星」TOP 10 &#xff0c; C/C 领域新星创作者&#x1f49f; 作 者&#xff1a;锡兰_CC ❣️&#x1f4dd; 专 栏&#xff1a;【OpenCV • c】计算机视觉&#x1f308; 若有帮助&#xff0c;还请关注➕点赞➕收藏&#xff…

C# Emgu.CV 条码检测

效果 项目 代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using Emgu.CV; using Emgu.CV.Util; using static Emgu.C…

机器人制作开源方案 | 桌面级机械臂--本体说明+驱动及控制

一、本体说明 1. 机械臂整体描述 该桌面级机械臂为模块化设计&#xff0c;包含主机模块1个、转台模块1个、二级摆动模块1个、可编程示教盒1个、2种末端执行器、高清摄像头&#xff0c;以及适配器、组装工具、备用零件等。可将模块快速组合为一个带被动关节的串联3自由度机械臂…

【业务功能篇73】web系统架构演变-单体-集群-垂直化-服务化-微服务化

1.服务架构的演 1.1 单体架构 单体架构应该是我们最先接触到的架构实现了&#xff0c;在单体架构中使用经典的三层模型&#xff0c;即表现层&#xff0c;业务逻辑层和数据访问层。 单体架构只适合在应用初期&#xff0c;且访问量比较下的情况下使用&#xff0c;优点是性价比很…

C#: Json序列化和反序列化,集合为什么多出来一些元素?

如下面的例子&#xff0c;很容易看出问题&#xff1a; 如果类本身的无参构造函数&#xff0c; 就添加了一些元素&#xff0c;那么在序列化&#xff0c;再反序列化&#xff0c;会导致元素增加。 如果要避免&#xff0c;必须添加&#xff1a; new JsonSerializerSettings() { …

拼多多anti-token分析

前言&#xff1a;拼多多charles抓包分析发现跟商品相关的请求头里都带了一个anti-token的字段且每次都不一样,那么下面的操作就从分析anti-token开始了 1.jadx反编译直接搜索 选中跟http相关的类对这个方法进行打印堆栈 结合堆栈方法调用的情况找到具体anti-token是由拦截器类f…

Spring 容器启动耗时统计

为了了解 Spring 为什么会启动那么久&#xff0c;于是看了看怎么统计一下加载 Bean 的耗时。 极简版 几行代码搞定。 import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor;import java.util.HashMap; imp…

k8s挂载映射操作详解

k8s投射数据卷 Projected Volume 在 k8s 中&#xff0c;有几种特殊的 Volume&#xff0c;它们的意义不是为了存放容器里的数据&#xff0c;也不是用来进行容器和宿主机之间的数据交换。"而是为容器提供预先定义好的数据。" 从容器的角度来看&#xff0c;这些 Volume…

SQL 错误 [22007]: ERROR: invalid input syntax for type date: ““

0. 背景 PG数据库一张表有这样一个varchar类型的字段end_date,存储的值是格式化后的年月日日期如 2024-08-10 现在我需要根据当前日期与end_date的差值作为where条件过滤,我的写法 select …… from my_table_name where current_date - cast (end_date as date) >100报错…

五度易链最新“产业大数据服务解决方案”亮相,打造数据引擎,构建智慧产业

快来五度易链官网 点击网址【http://www.wdsk.net/】 看看我们都发布了哪些新功能!!! 自2015年布局产业大数据服务行业以来&#xff0c;“五度易链”作为全国产业大数据服务行业先锋企业&#xff0c;以“让数据引领决策&#xff0c;以智慧驾驭未来”为愿景&#xff0c;肩负“打…

linux中互斥锁,自旋锁,条件变量,信号量,与freeRTOS中的消息队列,信号量,互斥量,事件的区别

RTOS 对于目前主流的RTOS的任务&#xff0c;大部分都属于并发的线程。 因为MCU上的资源每个任务都是共享的&#xff0c;可以认为是单进程多线程模型。 【freertos】003-任务基础知识 在没有操作系统的时候两个应用程序进行消息传递一般使用全局变量的方式&#xff0c;但是如…

基于Java+SpringBoot+Vue前后端分离社区医院管理系统设计和实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

优化Python代理爬虫的应用

当我们在资源受限的环境中使用Python代理爬虫时&#xff0c;我们需要采取一些优化措施&#xff0c;以确保程序的高效性和稳定性。在本文中&#xff0c;我将分享一些关于如何优化Python代理爬虫在资源受限环境下的应用的实用技巧。 首先我们来了解&#xff0c;哪些情况算是资源…

【位运算进阶之----右移(>>)】

&#x1f604;嘻嘻&#xff0c;朋友们&#xff0c;大家好&#xff01;昨天我们学习了左移&#xff0c;今天我们来谈谈右移>>。 ⭐️简单来说&#xff0c;右移就是将一个数二进制表达整体向右移动&#xff0c;也就是去掉一个数的二进制表达的末位&#xff0c;右移一位就去…

Kaniko在containerd中无特权快速构建并推送容器镜像

目录 一、kaniko是什么 二、kaniko工作原理 三、kanijo工作在Containerd上 基于serverless的考虑&#xff0c;我们选择了kaniko作为镜像打包工具&#xff0c;它是google提供了一种不需要特权就可以构建的docker镜像构建工具。 一、kaniko是什么 kaniko 是一种在容器或 Kube…

字符集(Latin1,GBK,utf8,utf8mb4)

Latin1 1个字符占一个字节GBK 1个字符占两个字节utf8utfmb3 1个字节占三个字节utf8mb4 1个字符占四个字节