构建大语言模型应用:数据准备(第二部分)

本专栏通过检索增强生成(RAG)应用的视角来学习大语言模型(LLM)。

本系列文章

  1. 简介
  2. 数据准备(本文)
  3. 句子转换器
  4. 向量数据库
  5. 搜索与检索
  6. 大语言模型
  7. 开源检索增强生成
  8. 评估
  9. 大语言模型服务
  10. 高级检索增强生成 RAG

在这里插入图片描述

如上图所示,是检索增强生成(RAG)的数据准备流程

在上一篇文章中,我们深入探讨了检索增强生成(RAG)流程,全面了解了它的各个组成部分。

任何机器学习应用的初始阶段都需要进行数据准备。这包括建立数据摄取流程以及对数据进行预处理,使其与推理流程兼容。

在本文中,我们将把注意力转向检索增强生成(RAG)的数据准备方面。目标是有效地组织和构建数据结构,确保在我们的应用程序中能够以最佳性能找到答案。

下面让我们深入了解细节。

1. 步骤一:数据摄取

构建一个用户友好的聊天机器人,始于明智的数据选择。这篇博客将探讨如何为成功的语言模型(LLM)应用有效地收集、管理和清理数据。

  • 明智选择:确定数据源,从门户网站到应用程序编程接口(API),并设置一个推送机制,以便为你的大语言模型应用持续更新数据。
  • 数据治理至关重要:预先实施数据治理政策。对文档来源进行审核和编目,编辑掉敏感数据,并为上下文训练奠定基础。
  • 质量检查:评估数据的多样性、规模和噪声水平。质量较低的数据集会使回复质量下降,因此需要一个早期分类机制。
  • 保持领先:即使在快节奏的大语言模型开发中,也要坚持数据治理。这可以降低风险,并确保可扩展、稳健的数据提取。
  • 实时清理:从诸如Slack这样的平台获取数据?实时过滤掉噪声、拼写错误和敏感内容,以打造一个干净、有效的大语言模型应用。

2. 步骤二:数据清洗

我们文件的每一页都会转换为一个文档对象,并且有两个基本组成部分:页面内容(page_content)和元数据(metadata)。

页面内容展示了直接从文档页面提取的文本内容。

元数据是一组至关重要的附加详细信息,比如文档的来源(它所源自的文件)、页码、文件类型以及其他信息要点。元数据在发挥其作用并生成有深刻见解的答案时,会记录它所利用的特定来源。
在这里插入图片描述

更多内容:Data Loading

为了实现这一点,我们利用强大的工具,如数据加载器(Data Loaders),这些工具由像LangChain和Llamaindex这样的开源库提供。这些库支持各种格式,从PDF和CSV到HTML、Markdown,甚至是数据库。

!pip install pypdf
!pip install langchain
# 对于PDF文件,我们需要从langchain框架中导入PyPDFLoader
from langchain_community.document_loaders import PyPDFLoader# 对于CSV文件,我们需要导入csv_loader
# 对于Doc文件,我们需要导入UnstructuredWordDocumentLoader
# 对于文本文档,我们需要导入TextLoaderfilePath = "/content/A_miniature_version_of_the_course_can_be_found_here__1701743458.pdf"
loader = PyPDFLoader(filePath) 
# 加载文档
pages = loader.load_and_split()
print(pages[0].page_content)

这种方法的一个优点是可以通过页码来检索文档。

3. 步骤三:分块

在这里插入图片描述

3.1. 为什么要分块?

在应用程序领域中,关键在于你如何处理数据——无论是Markdown文件、PDF文件还是其他文本文件。想象一下:你有一个庞大的PDF文件,并且你渴望就其内容提出问题。问题在于,传统的将整个文档和你的问题一股脑抛给模型的方法并不管用。为什么呢?嗯,让我们来谈谈模型上下文窗口的局限性。

以GPT-3.5 及其类似模型为例。可以把上下文窗口想象成窥视文档的一个窗口,通常只限于一页或几页的内容。那么,一次性共享整个文档呢?不太现实。但是别担心!

诀窍在于对数据进行分块。将其分解为易于处理的部分,只将最相关的分块发送给模型。这样,你就不会让模型不堪重负,并且能够获得你渴望的精确见解。

通过将我们的结构化文档分解为可管理的分块,我们使大语言模型能够以无与伦比的效率处理信息。不再受页面限制的约束,这种方法确保关键细节不会在处理过程中丢失。

3.2. 分块前的考虑因素

  • 文档的结构和长度
    • 长文档:书籍、学术文章等。
    • 短文档:社交媒体帖子、客户评论等。
  • 嵌入模型:分块大小决定了应该使用哪种嵌入模型。
  • 预期查询:应用场景是什么?

3.3. 分块大小

  • 小块大小:例如:单个句子 → 生成时的上下文信息较少。
  • 大块大小:例如:整页、多个段落、整个文档。在这种情况下,分块涵盖更多信息,这可以通过更多的上下文来提高生成的有效性。
3.3.1. 选择分块大小

在这里插入图片描述

  • 大语言模型上下文窗口:对可以输入到大语言模型的数据量有限制。
  • 前K个检索到的分块:假设大语言模型有一个10,000个Token的上下文窗口大小,我们为给定的用户查询预留大约1000个Token,为指令提示和聊天记录预留2000个Token,那么只剩下7000个Token用于其他任何信息。假设我们打算将K = 10,即前10个分块传递给大语言模型,这意味着我们将剩余的7000个Token除以总共10个分块,那么每个分块的最大大小约为700个Token。
  • 分块大小范围:下一步是选择一系列可能的分块大小进行测试。如前所述,选择应考虑内容的性质(例如,短消息或长篇文档)、你将使用的嵌入模型及其能力(例如,标记限制)。目标是在保留上下文和保持准确性之间找到平衡。首先探索各种分块大小,包括较小的分块(例如,128或256个Token)以捕获更精细的语义信息,以及较大的分块(例如,512或1024个Token)以保留更多上下文。
  • 评估每个分块大小的性能:要测试各种分块大小,你可以使用多个索引,或者使用具有多个命名空间的单个索引。使用具有代表性的数据集,为你想要测试的分块大小创建嵌入,并将它们保存在你的索引(或多个索引)中。然后,你可以运行一系列查询,通过这些查询评估质量,并比较各种分块大小的性能。这很可能是一个迭代过程,你针对不同的查询测试不同的分块大小,直到你能够确定适合你的内容和预期查询的性能最佳的分块大小。

高上下文长度的限制:由于Transformer模型的自注意力机制,高上下文长度可能会导致时间和内存呈二次方增加。

在LlamaIndex发布的这个例子中,你可以从下面的表格中看到,随着分块大小的增加,平均响应时间会有小幅上升。有趣的是,平均忠实度似乎在分块大小为1024时达到峰值,而平均相关性随着分块大小的增加持续提高,也在分块大小为1024时达到峰值。这表明分块大小为1024可能在响应时间和回复质量(以忠实度和相关性衡量)之间达到最佳平衡。
在这里插入图片描述

3.4. 分块方法

有不同的分块方法,并且每种方法可能适用于不同的情况。通过研究每种方法的优缺点,我们的目标是确定应用它们的合适场景。

3.4.1. 固定大小分块

我们决定每个分块中的标记数量,并可选择添加重叠部分以确保效果。为什么要重叠呢?是为了确保语义上下文的丰富性在各个分块之间保持完整。

为什么选择固定大小呢?在大多数情况下,这是最佳选择。它不仅计算成本低,节省处理能力,而且使用起来也很方便。无需复杂的自然语言处理库,只需用固定大小的分块优雅地分解你的数据即可。

以下是使用LangChain进行固定大小分块的示例:

text = "..." # 你的文本
from langchain.text_splitter import CharacterTextSplitter
text_splitter = CharacterTextSplitter(separator = "\n\n",chunk_size = 256,chunk_overlap  = 20
)
docs = text_splitter.create_documents([text])
3.4.2. “上下文感知”分块

这些是一组利用我们正在分块的内容的特性,并对其应用更复杂分块的方法。以下是一些示例:

3.4.2.1. 句子分割

正如我们之前提到的,许多模型针对嵌入句子级别的内容进行了优化。自然地,我们会使用句子分块,并且有几种方法和工具可用于实现这一点,包括:

  • 简单分割:最直接的方法是按句号(“.”)和换行符分割句子。虽然这可能快速且简单,但这种方法不会考虑所有可能的边界情况。这是一个非常简单的示例:
text = "..." # 你的文本
docs = text.split(".")
  • NLTK:自然语言工具包(NLTK)是一个流行的用于处理人类语言数据的Python库。它提供了一个句子标记器,可以将文本分割成句子,有助于创建更有意义的分块。例如,要将NLTK与LangChain一起使用,可以执行以下操作:
text = "..." # 你的文本
from langchain.text_splitter import NLTKTextSplitter
text_splitter = NLTKTextSplitter()
docs = text_splitter.split_text(text)
  • spaCy:spaCy是另一个用于自然语言处理任务的强大Python库。它提供了一种复杂的句子分割功能,可以有效地将文本分割成单独的句子,从而在生成的分块中更好地保留上下文。例如,要将spaCy与LangChain一起使用,可以执行以下操作:
text = "..." # 你的文本
from langchain.text_splitter import SpacyTextSplitter
text_splitter = SpaCyTextSplitter()
docs = text_splitter.split_text(text)
3.4.2.2. 递归分块

来认识一下我们的秘密武器:LangChain的RecursiveCharacterTextSplitter。这个多功能工具可以根据选定的字符优雅地分割文本,同时保留语义上下文。想想双换行符、单换行符和空格——它就像把信息雕琢成易于理解的、有意义的部分。

它是如何工作的呢?很简单。只需传入文档并指定所需的分块长度(假设为1000个单词)。你甚至可以微调分块之间的重叠部分。

以下是如何使用LangChain进行递归分块的示例:

text = "..." # 你的文本
from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(# 设置一个非常小的分块大小,仅用于演示。chunk_size = 256,chunk_overlap  = 20
)
docs = text_splitter.create_documents([text])
3.4.2.3. 特殊分块

Markdown和LaTeX是你可能会遇到的两种结构化和格式化内容的示例。在这些情况下,你可以使用特殊的分块方法,在分块过程中保留内容的原始结构。

  • Markdown:Markdown是一种常用于格式化文本的轻量级标记语言。通过识别Markdown语法(例如,标题、列表和代码块),你可以根据其结构和层次结构智能地分割内容,从而得到语义更连贯的分块。例如:
from langchain.text_splitter import MarkdownTextSplitter
markdown_text = "..."
markdown_splitter = MarkdownTextSplitter(chunk_size=100, chunk_overlap=0)
docs = markdown_splitter.create_documents([markdown_text])
markdown_splitter = MarkdownTextSplitter(chunk_size=100, chunk_overlap=0)
docs = markdown_splitter.create_documents([markdown_text])
  • LaTeX:LaTeX是一种常用于学术论文和技术文档的文档准备系统和标记语言。通过解析LaTeX命令和环境,你可以创建尊重内容逻辑组织(例如,章节、子章节和方程式)的分块,从而得到更准确和上下文相关的结果。例如:
from langchain.text_splitter import LatexTextSplitter
latex_text = "..."
latex_splitter = LatexTextSplitter(chunk_size=100, chunk_overlap=0)
docs = latex_splitter.create_documents([latex_text])

3.5. 多模态分块

在这里插入图片描述

  • 从文档中提取表格和图像:使用LayoutPDFReader、Unstructured等工具。提取的表格和图像可以用标题、描述和摘要等元数据进行标记。
  • 多模态方法
    • 文本嵌入:总结图像和表格。
    • 多模态嵌入:使用可以处理原始图像的嵌入模型。

4. 步骤四:Tokenization 标记化

在这里插入图片描述

最常用标记化方法总结

标记化包括将短语、句子、段落或整个文本文档分割成更小的单元,例如单个单词或术语。在本文中,我们将了解主要的标记化方法以及它们目前的应用场景。我建议你也查看一下Hugging Face制作的这个标记器总结,以获取更深入的指南。

4.1. 词级标记化 Word-Level Tokenization

词级标记化包括将文本分割成单词单元。为了正确地进行标记化,需要考虑一些注意事项。

  • 空格和标点符号标记化

将文本分割成较小的块比看起来要难,并且有多种方法可以做到这一点。例如,让我们看一下下面的句子:

“Don't you like science? We sure do.”

对这段文本进行标记化的一种简单方法是按空格分割,这将得到:

["Don't", "you", "like", "science?", "We", "sure", "do."]

如果我们看一下标记“science?”“do.”,我们会注意到标点符号与单词“science”“do”连在一起,这并不理想。我们应该考虑标点符号,这样模型就不必学习一个单词及其后面可能出现的每个标点符号的不同表示形式,否则模型必须学习的表示形式数量会激增。
考虑标点符号后,对我们的文本进行标记化将得到:

["Don", "'", "t", "you", "like", "science", "?", "We", "sure", "do", "."]
  • 基于规则的标记化

前面的标记化方法比单纯基于空格的标记化要好一些。然而,我们可以进一步改进标记化处理“Don't”这个单词的方式。“Don't”代表“do not”,所以用类似于["Do", "n't"]这样的方式进行标记化会更好。其他一些特定规则可以进一步改进标记化效果。

然而,根据我们应用于文本标记化的规则不同,对于相同的文本会生成不同的标记化输出。因此,只有当你向预训练模型输入的内容是使用与训练数据标记化相同的规则进行标记化时,预训练模型才能正常运行。

  • 词级标记化的问题

词级标记化对于大规模文本语料库可能会导致问题,因为它会生成非常大的词汇表。例如,Transformer XL语言模型使用空格和标点符号标记化,导致词汇表大小达到267,000。
由于词汇表如此之大,模型的输入和输出层有一个巨大的嵌入矩阵,这增加了内存和时间复杂度。作为参考,Transformer模型的词汇表大小很少会超过50,000。

4.2. 字符级标记化 Character-Level Tokenization

那么,如果词级标记化不可行,为什么不直接对字符进行标记化呢?

尽管字符级标记化会极大地降低内存和时间复杂度,但它会使模型更难学习到有意义的输入表示。例如,学习字母“t”的一个有意义且与上下文无关的表示,要比学习单词“today”的与上下文无关的表示难得多。

因此,字符级标记化往往会导致性能下降。为了兼顾两者的优点,Transformer模型通常会使用一种介于词级和字符级标记化之间的混合方法,称为子词标记化。

4.3. 子词标记化 Subword Tokenization

子词标记化算法基于这样一个原则:常用词不应被分割成更小的子词,而罕见词则应被分解为有意义的子词。

例如,“annoyingly”可能被认为是一个罕见词,可以分解为“annoying”“ly”“annoying”“ly”作为独立的子词出现的频率会更高,同时,“annoyingly”的意思通过“annoying”“ly”的组合含义得以保留。

除了使模型的词汇表大小合理之外,子词标记化还能让模型学习到有意义的、与上下文无关的表示。此外,子词标记化可用于处理模型从未见过的单词,方法是将它们分解为已知的子词。

现在让我们来看看几种不同的子词标记化方法。

字节对编码(Byte-Pair Encoding: BPE)

字节对编码(BPE)依赖于一个预标记器,该预标记器将训练数据分割成单词(例如像GPT-2和RoBERTa中使用的基于空格的标记化方法)。

在预标记化之后,BPE创建一个基础词汇表,该词汇表由语料库中唯一单词集合中出现的所有符号组成,并学习合并规则,以便从基础词汇表中的两个符号形成一个新符号。这个过程会不断迭代,直到词汇表达到所需的大小。

词块(WordPiece)

用于BERT、DistilBERT和ELECTRA的词块方法与BPE非常相似。WordPiece首先将词汇表初始化为包含训练数据中出现的每个字符,然后逐步学习一定数量的合并规则。与BPE不同的是,WordPiece不会选择最频繁出现的符号对,而是选择一旦添加到词汇表中就能使训练数据出现概率最大化的那个符号对。

直观地说,WordPiece与BPE略有不同,因为它会评估合并两个符号所带来的损失,以确保这样做是值得的。

一元语法(Unigram)

与BPE或WordPiece不同,一元语法(Unigram)将其基础词汇表初始化为大量的符号,然后逐步削减每个符号,以获得一个较小的词汇表。例如,基础词汇表可以对应于所有预标记化的单词和最常见的子字符串。Unigram通常与SentencePiece一起使用。

句子片段(SentencePiece)

到目前为止描述的所有标记化算法都有一个相同的问题:它们都假定输入文本使用空格来分隔单词。然而,并非所有语言都使用空格来分隔单词。

为了从根本上解决这个问题,SentencePiece将输入视为一个原始输入流,因此将空格也包含在要使用的字符集合中。然后,它使用BPE或Unigram算法来构建合适的词汇表。

使用SentencePiece的模型示例包括ALBERT、XLNet、MarianMT和T5。

OpenAI标记化可视化:https://platform.openai.com/tokenizer

结论

在这篇博客中,我们探讨了检索增强生成(RAG)应用程序的数据准备过程,强调了为实现最佳性能进行高效的数据结构化。它涵盖了将原始数据转换为结构化文档、创建相关的数据块,以及子词标记化等标记化方法。我们强调了选择合适数据块大小的重要性,以及对每种标记化方法的考量因素。这篇文章为根据特定应用需求定制数据准备工作提供了深刻见解。

鸣谢

在这篇博客文章中,我们汇集了来自各种来源的信息,包括研究论文、技术博客、官方文档等。每个来源都在相应的图片下方进行了适当的标注,并提供了来源链接。

以下是参考列表:

  • https://dataroots.io/blog/aiden-data-ingestion
  • https://www.pinecone.io/learn/chunking-strategies/
  • https://www.youtube.com/watch?v=uhVMFZjUOJI&t=1209s
  • https://medium.com/nlplanet/two-minutes-nlp-a-taxonomy-of-tokenization-methods-60e330aacad3
  • https://medium.com/@vipra_singh/building-llm-applications-data-preparation-part-2-b7306d224245

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

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

相关文章

Linux 随机数据生成

目录 一. /dev/urandom1.1 dd 命令1.2 head命令1.3 随机字母 二. openssl 命令三. yes命令 一. /dev/urandom ⏹/dev/urandom 是 Linux 和 Unix 系统中的一个特殊文件,它是一个伪随机数生成器,用于提供高吞吐量的随机数据。 1.1 dd 命令 bs1M count10…

项目如何安装本地tgz包并配置局部registry

一、判断包来源是否正确 1. 检查url curl <registry_url>2. 查看包是否存在 npm view <package_name> --registry<registry_url>二、局部registry配置步骤&#xff1a; 1. 全局配置 如果你希望对所有项目生效&#xff0c;可以将这行配置添加到全局.npmr…

QCustomPlot入门

QCustomPlot 是一个基于 Qt 的 C++ 绘图库,专注于高效、美观的 2D 数据可视化。进入QCustomPlot下载页,下载最新的完整包(包含:源码、文档、示例)。 一、核心架构设计 1. 分层架构模型 层级主要组件职责说明用户接口层QCustomPlot 类提供顶层API,管理所有子组件逻辑控制…

C语言快速入门-C语言基础知识

这个c语言入门&#xff0c;目标人群是有代码基础的&#xff0c;例如你之前学过javaSE&#xff0c;看此文章可能是更有帮助&#xff0c;会让你快速掌握他们之间的差异&#xff0c;文章内容大部分都是泛谈&#xff0c;详细的部分我会在之后时间发布&#xff0c;我也在慢慢学习&am…

【商城实战(91)】安全审计与日志管理:为电商平台筑牢安全防线

【商城实战】专栏重磅来袭!这是一份专为开发者与电商从业者打造的超详细指南。从项目基础搭建,运用 uniapp、Element Plus、SpringBoot 搭建商城框架,到用户、商品、订单等核心模块开发,再到性能优化、安全加固、多端适配,乃至运营推广策略,102 章内容层层递进。无论是想…

信息安全工程师第 1 章

《信息安全工程师教程(第2版)》第一章 一、网络信息安全基本概念与重要性 网络信息安全定义 狭义:保障信息系统的机密性(C)、完整性(I)、可用性(A)——CIA三性。广义:涵盖国家安全、经济安全、社会安全等的“大安全”。法律依据:《网络安全法》定义网络安全为防范攻…

为什么视频文件需要压缩?怎样压缩视频体积即小又清晰?

在日常生活中&#xff0c;无论是为了节省存储空间、便于分享还是提升上传速度&#xff0c;我们常常会遇到需要压缩视频的情况。本文将介绍为什么视频需要压缩&#xff0c;压缩视频的好处与坏处&#xff0c;并教你如何使用简鹿视频格式转换器轻松完成MP4视频文件的压缩。 为什么…

网络空间安全(45)PHP入门学习

一、PHP文件与结构 PHP文件扩展名&#xff1a;PHP文件通常以.php作为扩展名&#xff0c;例如index.php。 PHP代码嵌入&#xff1a;PHP代码可以嵌入到HTML文件中&#xff0c;通常使用<?php ... ?>标签包围PHP代码。短标签<? ... ?>在某些配置下也可以使用&…

深入 OpenPDF:高级 PDF 生成与操作技巧

1 引言 1.1 项目背景 在许多企业级应用中,生成和操作 PDF 文档是一个常见的需求。PDF(Portable Document Format)因其格式统一、易于打印和分发而被广泛使用。本文将介绍如何使用 OpenPDF 库在 Java 项目中生成和操作 PDF 文档。 1.2 技术选型理由 OpenPDF:OpenPDF 是一…

力扣hot100——最长连续序列(哈希unordered_set)

题目链接&#xff1a;最长连续序列 1、错解&#xff1a;数组做哈希表&#xff08;内存超出限制&#xff09; int longestConsecutive(vector<int>& nums) {vector<bool> hash(20000000010, false);for(int i0; i<nums.size();i){hash[1000000000nums[i]]t…

Qt中信号带参传值

在我们的Qt信号中是可以进行参数的传递的&#xff0c;不过格式上与写普通函数不同。 这是头文件中定义一个含参信号和一个含参槽函数 我们再来看它们两个的绑定 。第一行的clicked()和on_btn_clicked()就是普通无参信号和槽的绑定&#xff1b;第二行就是上图中两个带参信号和槽…

CSS3学习教程,从入门到精通, CSS3 列表控制详解语法知识点及案例代码(24)

CSS3 列表控制详解 CSS 列表控制的语法知识点及案例代码的详细说明&#xff0c;包括 list-style-type、list-style-image、list-style-position 和 list-style 的用法。 1. list-style-type 属性 list-style-type 属性用于设置列表项标记的类型。 语法 list-style-type: v…

用Deepseek写扫雷uniapp小游戏

扫雷作为Windows系统自带的经典小游戏&#xff0c;承载了许多人的童年回忆。本文将详细介绍如何使用Uniapp框架从零开始实现一个完整的扫雷游戏&#xff0c;包含核心算法、交互设计和状态管理。无论你是Uniapp初学者还是有一定经验的开发者&#xff0c;都能从本文中获得启发。 …

Dust3r、Mast3r、Fast3r

目录 一.Dust3r 1.简述 2.PointMap与ConfidenceMap 3.模型结构 4.损失函数 5.全局对齐 二.Mast3r 1.简述 2.MASt3R matching 3.MASt3R sfm 匹配与标准点图 BA优化 三.Fast3r 1.简述 2.模型结构 3.损失函数 三维重建是计算机视觉中的一个高层任务&#xff0c;包…

学习不同电脑cpu分类及选购指南

学习不同电脑cpu分类及选购指南 关于电脑cpu 学习不同电脑cpu分类及选购指南一、CPU型号的核心组成与命名规则Intel命名规则:AMD命名规则:代数:具体型号:cpu后缀:Intel常见后缀及其含义:AMD后缀常见后缀及其含义:二、主流品牌CPU的分类与性能差异三、区分CPU型号的实用方…

【身份安全】零信任安全框架梳理(一)

目录 零信任网络安全防护理念一、定义零信任原则 二、零信任实现方式三、零信任的核心机制和思想1. 持续验证&#xff08;Continuous Verification&#xff09;2. 多因素认证&#xff08;MFA&#xff09;与强身份验证3. 细粒度权限控制&#xff08;最小权限原则&#xff09;4. …

【LeetCode Solutions】LeetCode 101 ~ 105 题解

CONTENTS LeetCode 101. 对称二叉树&#xff08;简单&#xff09;LeetCode 102. 二叉树的层序遍历&#xff08;中等&#xff09;LeetCode 103. 二叉树的锯齿形层序遍历&#xff08;中等&#xff09;LeetCode 104. 二叉树的最大深度&#xff08;简单&#xff09;LeetCode 105. 从…

革新汽车安全通信技术,美格智能全系车载通信模组支持NG-eCall

根据QYR&#xff08;恒州博智&#xff09;的统计及预测&#xff0c;2024年全球汽车无线紧急呼叫&#xff08;eCall&#xff09;设备市场销售额达到了25.17亿美元&#xff0c;预计2031年将达到44.97亿美元&#xff0c;年复合增长率&#xff08;CAGR 2025-2031&#xff09;为8.8%…

Redis-04.Redis常用命令-字符串常用命令

一.字符串操作命令 set name jack 点击左侧name&#xff0c;显示出值。 get name get abc&#xff1a;null setex key seconds value&#xff1a;设置过期时间&#xff0c;过期后该键值对将会被删除。 然后再get&#xff0c;在过期时间内可以get到&#xff0c;过期get不到。…

一文总结常见项目排查

慢sql排查 怎么排查 通过如下命令&#xff0c;开启慢 SQL 监控&#xff0c;执行成功之后&#xff0c;客户端需要重新连接才能生效。 -- 开启慢 SQL 监控 set global slow_query_log 1; 默认的慢 SQL 阀值是10秒&#xff0c;可以通过如下语句查询慢 SQL 的阀值。 -- 查询慢…