Hugging face Transformers(3)—— Tokenizer

  • Hugging Face 是一家在 NLP 和 AI 领域具有重要影响力的科技公司,他们的开源工具和社区建设为NLP研究和开发提供了强大的支持。它们拥有当前最活跃、最受关注、影响力最大的 NLP 社区,最新最强的 NLP 模型大多在这里发布和开源。该社区也提供了丰富的教程、文档和示例代码,帮助用户快速上手并深入理解各类 Transformer 模型和 NLP 技术
  • Transformers 库是 Hugging Face 最著名的贡献之一,它最初是 Transformer 模型的 pytorch 复现库,随着不断建设,至今已经成为 NLP 领域最重要,影响最大的基础设施之一。该库提供了大量预训练的模型,涵盖了多种语言和任务,成为当今大模型工程实现的主流标准,换句话说,如果你正在开发一个大模型,那么按 Transformer 库的代码格式进行工程实现、将 check point 打包成 hugging face 格式开源到社区,对于推广你的工作有很大的助力作用。本系列文章将介绍 Transformers库 的基本使用方法
  • 前文:Hugging face Transformers(2)—— Pipeline

文章目录

  • 1. Tokenizer 及其基本使用
    • 1.1 保存与加载
    • 1.2 句子分词
    • 1.3 索引转换
    • 1.4 截断和填充
    • 1.5 附加输入信息
    • 1.6 处理 batch 数据
  • 2. Fast/Slow Tokenizer
  • 3. 加载特殊 Tokenizer

1. Tokenizer 及其基本使用

  • Tokenizer 是将原始字符串转换为模型可以计算的数值形式(通常是 token IDs)的工具。不同的模型可能需要不同的 tokenizer,因为不同的预训练任务和数据集可能会导致不同的词汇表(vocabulary)和 tokenization 策略。
  • Tokenizer 用于数据预处理,其作用包括
    1. 分词:使用分词器对文本数据进行分词 (字、字词)
    2. 构建词典:根据数据集分词的结果,构建词典映射 (这步并不绝对,如果采用预训练词向量,词典映射要根据词向量文件进行处理)
    3. 数据转换:根据构建好的词典,将分词处理后的数据做映射,将文本序列转换为数字序列。其中可能涉及添加特殊标记(如 [CLS][SEP][MASK] 等),以便模型能够识别文本的不同部分或执行特定的任务(如分类、问答等)
    4. 数据填充与截断:在以batch输入到模型的方式中,需要对过短的数据进行填充,过长的数据进行截断,保证数据长度符合模型能接受的范围,同时batch内的数据维度大小一致

1.1 保存与加载

  • 如前文 Hugging face Transformers(2)—— Pipeline 3.2 节所述,可以用 AutoTokenizer 自动类,从模型地址直接识别、创建并初始化所需的 tokenizer 对象。这里我们还是使用前文的中文情感分类模型的 tokenizer
    # AutoTokenizer 包可以根据传入的参数(如模型名)自动判断所需的 tokenizer
    from transformers import AutoTokenizer# 样例字符串
    sen = "这是一段测试文本"# 从 hugging face 加载,输入模型名称即可加载对应的分词器
    tokenizer = AutoTokenizer.from_pretrained("uer/roberta-base-finetuned-dianping-chinese")
    tokenizer
    
    BertTokenizerFast(name_or_path='uer/roberta-base-finetuned-dianping-chinese', vocab_size=21128, model_max_length=1000000000000000019884624838656, is_fast=True, padding_side='right', truncation_side='right', special_tokens={'unk_token': '[UNK]', 'sep_token': '[SEP]', 'pad_token': '[PAD]', 'cls_token': '[CLS]', 'mask_token': '[MASK]'}, clean_up_tokenization_spaces=True),  added_tokens_decoder={0: AddedToken("[PAD]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),100: AddedToken("[UNK]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),101: AddedToken("[CLS]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),102: AddedToken("[SEP]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),103: AddedToken("[MASK]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),
    }
    
    从打印信息可见,这是一个 BERT 模型的 Tokenizer,其中有五个特殊符号,在右侧进行填充或截断…
  • 第一次创建 Tokenizer 对象时,词表等相关配置文件会下载并保存至默认路径 C:\Users\username\.cache\huggingface\hub,之后会默认从此处重新加载。可以将构造的 tokenizer 对象手动保存到指定路径,并从指定路径加载
    # 自动下载的 model 和 tokenizer 等组件位于 C:\Users\username\.cache\huggingface\hub 中
    # 可以把 tokenizer 单独保存到指定路径
    tokenizer.save_pretrained("./roberta_tokenizer")# 可以从本地加载保存的 tokenizer
    tokenizer = AutoTokenizer.from_pretrained("./roberta_tokenizer")
    

1.2 句子分词

  • Tokenizer 工作的第一步是文本分割,即将原始输入字符串拆开成一系列字符、词、字节码或短句(称之为token。在中文自然语言处理中,分词尤为重要,因为中文的词与词之间没有空格这样明显的分隔符。

  • 根据分词方法不同,对应的词表也会有所区别。一般而言,较大的词表可以包含更多的词汇,有助于模型更好地理解和表达文本,提高模型性能,增强泛化能力。然而,随着词表尺寸的增加,模型的计算复杂度和内存需求也会相应增加。可以通过 Tokenizer 对象的 .vocab 属性查看词表

    tokenizer.vocab
    
    {'##净': 14169,'ま': 567,'##copyright': 13291,'疡': 4550,'抢': 2843,'枇': 3355,'##尘': 15269,'贺': 6590,'ne': 10564,'庸': 2435,'##馬': 20736,'臾': 5640,'勖': 1241,'##粱': 18175,'##⒋': 13574,'褥': 6191,'doc': 9656,'釁': 7022,'alex': 10179,'##フト': 10868,'屹': 2256,'yumi': 11697,'##nne': 12866,'莫': 5811,'816': 10937,
    ...'##躍': 19770,'皺': 4653,'##ろ': 10460,'##孪': 15169,...}
    
  • Transformers 库的 tokenizer 支持传入原始字符串或原始字符串列表,如下所示

    tokens = tokenizer.tokenize(sen)
    print(tokens)   # ['这', '是', '一', '段', '测', '试', '文', '本']tokens = tokenizer.tokenize([sen, sen])
    print(tokens)   # ['这', '是', '一', '段', '测', '试', '文', '本', '这', '是', '一', '段', '测', '试', '文', '本']
    

1.3 索引转换

  • 只进行分词,得到的还是一些字符串和字符对象,还需要进行一步索引转换才能变成可计算的数值数据。所谓索引转换,其实就是把分词结果一一替换为词表中的索引(称之为 token id),之后在做 embedding 的时候,这些 id 会先转换为 one-hot 向量,再通过线性层投影到嵌入空间(也称为 lookup table 操作),此后就可以在隐空间向量上进行注意力计算了
  • 结合 1.2 节的分词和索引转换,完整的 tokenize 过程如下
    # Tokenize流程:原始字符串 -> token 序列 -> id 序列
    tokens = tokenizer.tokenize(sen)
    ids = tokenizer.convert_tokens_to_ids(tokens)
    print(ids)		# [6821, 3221, 671, 3667, 3844, 6407, 3152, 3315]# 也可以逆向操作:id 序列-> token 序列
    tokens = tokenizer.convert_ids_to_tokens(ids)
    print(tokens)	# ['这', '是', '一', '段', '测', '试', '文', '本']# 也可以逆向操作:token 序列 -> 字符串
    str_sen = tokenizer.convert_tokens_to_string(tokens)
    print(str_sen)	# 这 是 一 段 测 试 文 本
    
  • Transformers 库还提供称为 “编码” 和 “解法” 的简便方法,实现从原始字符串到 id 序列相互转换的一步操作
    # “编码”: 原始字符串 -> id 序列
    ids = tokenizer.encode(sen, add_special_tokens=True)        # add_special_tokens 在 tokenize 时序列设置特殊 token
    print(ids)                                                  # 注意到首尾多了特殊 token [CLS](101) 和 [SEP](102)
    # “解码”:id 序列 -> 原始字符串
    str_sen = tokenizer.decode(ids, skip_special_tokens=False)  # skip_special_tokens 可以跳过可能存在的特殊 token
    print(str_sen)
    str_sen = tokenizer.decode(ids, skip_special_tokens=True)
    print(str_sen)'''
    [101, 6821, 3221, 671, 3667, 3844, 6407, 3152, 3315, 102]
    [CLS] 这 是 一 段 测 试 文 本 [SEP]
    这 是 一 段 测 试 文 本
    '''
    
    注意,在 encode 方法传入 add_special_tokens 参数;在 decode 方法传入 skip_special_tokens 参数,可以控制特殊 token 的引入和跳过

1.4 截断和填充

  • 通常使用 batch 形式训练 Transformer 类模型,这要求我们把序列数据长度全部处理成和模型输入一致的状态。为此,需要进行截断或填充操作
    # 填充
    ids = tokenizer.encode(sen, padding="max_length", max_length=15)
    print(ids)  # [101, 6821, 3221, 671, 3667, 3844, 6407, 3152, 3315, 102, 0, 0, 0, 0, 0]# 截断
    ids = tokenizer.encode(sen, max_length=5, truncation=True)
    print(ids)  # [101, 6821, 3221, 671, 102]
    ids = tokenizer.encode(sen, max_length=5, truncation=False)	# 禁止截断则正常做 tokenize
    print(ids)  # [101, 6821, 3221, 671, 3667, 3844, 6407, 3152, 3315, 102]
    
  • 如上所示,通过在 encode 方法传入 max_length 参数控制最终序列长度,通过 padding 参数控制填充类型。注意到该 tokenizer 是在右侧进行 zero-padding 的,该设置可以在 1.1 节的 tokenizer 信息中观察到。另外,可以通过 truncation 参数控制是否截断

1.5 附加输入信息

  • 通常,Transformer 类模型的前向过程不止需要 token id,还需要各个 token id 的一些附加信息。比如在 BERT 的上下句预训练任务中,需要明确各个 token 所属的上下句信息;还需要 attention_mask 遮盖 zero padding 的部分,这些信息我们可以手动构造
    ids = tokenizer.encode(sen, padding="max_length", max_length=15)# 除 token 外,Transformer 类模型的输入往往还有一些附加信息
    attention_mask = [1 if idx != 0 else 0 for idx in ids]  # attention_mask 用于遮盖 zero padding 部分
    token_type_ids = [0] * len(ids)                         # bert 有一个判断上下句任务,模型预训练时需要 token 所属句子 id 信息
    ids, attention_mask, token_type_ids
    
    ([101, 6821, 3221, 671, 3667, 3844, 6407, 3152, 3315, 102, 0, 0, 0, 0, 0],[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
    
  • Transformers 库中,这些附件信息的生成方法被集成到 tokenizer 的实现中,通过 tokenizer.encode_plus() 方法或直接 tokenizer() 形式调用
    # 附加信息无需手动编写,tokenizer 中已经提供
    inputs = tokenizer.encode_plus(sen, padding="max_length", max_length=15)
    print(inputs)	# {'input_ids': [101, 6821, 3221, 671, 3667, 3844, 6407, 3152, 3315, 102, 0, 0, 0, 0, 0], 'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0]}# 另一种调用方法
    inputs = tokenizer(sen, padding="max_length", max_length=15)
    print(inputs)	# {'input_ids': [101, 6821, 3221, 671, 3667, 3844, 6407, 3152, 3315, 102, 0, 0, 0, 0, 0], 'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0]}
    

1.6 处理 batch 数据

  • 前文 1.2 节提到过,tokenizer 支持字符串和字符串列表形式的输入,其中后者是为了 batch 数据而专门设计的,可以有效提高 tokenize 效率。基本使用如下

    sens = ["AABBCCDDEEFF","哈哈哈哈哈哈哈哈哈哈哈","你好你好你好你好"
    ]
    res = tokenizer(sens)	# batch tokenize 不要求各原始字符串长度一致
    res
    
    {'input_ids': [[101, 9563, 10214, 8860, 9879, 8854, 9049, 102], [101, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 1506, 102], [101, 872, 1962, 872, 1962, 872, 1962, 872, 1962, 102]], 'token_type_ids': [[0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], 'attention_mask': [[1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]}
    
  • 对比单条操作+循环和成批量操作的时间消耗

    %%time
    # 单条循环处理,慢
    for i in range(1000):tokenizer(sen)'''
    CPU times: total: 172 ms
    Wall time: 242 ms
    '''
    
    %%time
    # 成 batch 批量计算,快
    tokenizer([sen] * 1000)'''
    CPU times: total: 78.1 ms
    Wall time: 27.9 ms
    '''
    

2. Fast/Slow Tokenizer

  • Transformer 库提供了两种 tokenizer

    1. FastTokenizer: 基于 Rust 实现,速度快,可以提供更多附加信息,类型名有后缀 Fast
    2. SlowTokenizer: 基于 python 实现,速度慢
  • 直接创建的 Tokenizer,如果存在 Fast 类型,则默认都是 Fast 类型

    sen = "快慢Tokenizer测试"
    fast_tokenizer = AutoTokenizer.from_pretrained("uer/roberta-base-finetuned-dianping-chinese")
    fast_tokenizer # 类型名有后缀 Fast
    
    BertTokenizerFast(name_or_path='uer/roberta-base-finetuned-dianping-chinese', vocab_size=21128, model_max_length=1000000000000000019884624838656, is_fast=True, padding_side='right', truncation_side='right', special_tokens={'unk_token': '[UNK]', 'sep_token': '[SEP]', 'pad_token': '[PAD]', 'cls_token': '[CLS]', 'mask_token': '[MASK]'}, clean_up_tokenization_spaces=True),  added_tokens_decoder={0: AddedToken("[PAD]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),100: AddedToken("[UNK]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),101: AddedToken("[CLS]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),102: AddedToken("[SEP]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),103: AddedToken("[MASK]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),
    }
    
  • 构造 Tokenizer 时,可以通过传入 use_fast=False 强制构造 Slow Tokenizer

    # 设置 use_fast=False 来构造 SlowTokenizer
    slow_tokenizer = AutoTokenizer.from_pretrained("uer/roberta-base-finetuned-dianping-chinese", use_fast=False)
    slow_tokenizer # 类型名无后缀 Fast
    
    BertTokenizer(name_or_path='uer/roberta-base-finetuned-dianping-chinese', vocab_size=21128, model_max_length=1000000000000000019884624838656, is_fast=False, padding_side='right', truncation_side='right', special_tokens={'unk_token': '[UNK]', 'sep_token': '[SEP]', 'pad_token': '[PAD]', 'cls_token': '[CLS]', 'mask_token': '[MASK]'}, clean_up_tokenization_spaces=True),  added_tokens_decoder={0: AddedToken("[PAD]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),100: AddedToken("[UNK]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),101: AddedToken("[CLS]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),102: AddedToken("[SEP]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),103: AddedToken("[MASK]", rstrip=False, lstrip=False, single_word=False, normalized=False, special=True),
    }
    

    注意到 Tokenizer 对象类型名没有 Fast 后缀了。两种 Tokenizer 具有明显的速度差距

    %%time
    fast_tokenizer([sen] * 10000)'''
    CPU times: total: 1.02 s
    Wall time: 349 ms
    '''
    
    %%time
    slow_tokenizer([sen] * 10000)'''
    CPU times: total: 2.89 s
    Wall time: 3.05 s
    '''
    
  • Fast Tokenizer 有时会返回一些额外信息,例如有时候原始输入字符串中的英文不会按字母分词,而是按词根词缀分词,这时相应的 token 会对应到原始字符串中的一个索引区域,Fast Tokenizer 可以通过设置 return_offsets_mapping=True 获取 token 和原始索引区域的对应信息

    sen = "快慢Tokenizer测试"
    inputs = fast_tokenizer(sen, return_offsets_mapping=True) # (只有 FastTokenizer 可以设置 return_offsets_mapping=True)
    print(sen)                       # 打印原始字符串
    print(inputs.word_ids())         # 打印各个 token 对应到原始字符串的 “词索引”,注意到原始字符串中 ”Tokenizer“ 这个词被拆成了4个token (只有 FastTokenizer 可以调用这个)
    print(inputs['offset_mapping'])  # offset_mapping 指示了各个 token 对应的原始字符串索引区域
    
    快慢Tokenizer测试
    [None, 0, 1, 2, 2, 2, 2, 3, 4, None]
    [(0, 0), (0, 1), (1, 2), (2, 4), (4, 7), (7, 10), (10, 11), (11, 12), (12, 13), (0, 0)]
    

3. 加载特殊 Tokenizer

  • 有些开源模型的 Tokenizer 没有嵌入到 Transformers 库中,而是由作者在开源时于其远程仓库中提供,这种情况下 Tokenizer 的行为可能和 Transformers 库中其他 Tokenizer 的一般行为有所不同,直接加载这些模型会报错

    tokenizer = AutoTokenizer.from_pretrained("Skywork/Skywork-13B-base", trust_remote_code=False)
    # ValueError: Loading Skywork/Skywork-13B-base requires you to execute the configuration file in that repo on your local machine. Make sure you have read the code there to avoid malicious use, then set the option `trust_remote_code=True` to remove this error.
    

    这时,需要在 .from_pretrained 方法中传入 trust_remote_code=True 对远程代码添加信任,才能正常下载目标 tokenizer

    tokenizer = AutoTokenizer.from_pretrained("Skywork/Skywork-13B-base", trust_remote_code=True)
    tokenizer
    
    You are using the legacy behaviour of the <class 'transformers_modules.Skywork.Skywork-13B-base.bc35915066fbbf15b77a1a4a74e9b574ab167816.tokenization_skywork.SkyworkTokenizer'>. This means that tokens that come after special tokens will not be properly handled. 
    SkyworkTokenizer(name_or_path='Skywork/Skywork-13B-base', vocab_size=65519, model_max_length=1000000000000000019884624838656, is_fast=False, padding_side='right', truncation_side='right', special_tokens={'bos_token': '<s>', 'eos_token': '</s>', 'unk_token': '<unk>'}, clean_up_tokenization_spaces=False),  added_tokens_decoder={0: AddedToken("<unk>", rstrip=False, lstrip=False, single_word=False, normalized=True, special=True),1: AddedToken("<s>", rstrip=False, lstrip=False, single_word=False, normalized=True, special=True),2: AddedToken("</s>", rstrip=False, lstrip=False, single_word=False, normalized=True, special=True),
    }
    
  • 下载之后,可以用前文 1.1 节方法将其保存到本地

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

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

相关文章

uniapp小程序接口返回文件流下载文件

uniapp小程序接口返回文件流数据&#xff0c;下载导出文件 使用uni.request post方法获取文件流&#xff0c;如果是get可以使用uni.downloadFile exportfun(){uni.request({url: xxx,data: {},method:POST,responseType: arraybuffer,header: {},success: (res) > {const …

Java并发编程-AQS详解及案例实战(上篇)

文章目录 AQS概述AQS 的核心概念AQS 的工作原理AQS 的灵活性使用场景AQS的本质:为啥叫做异步队列同步器AQS的核心机制“异步队列”的含义“同步器”的含义总结加锁失败的时候如何借助AQS异步入队阻塞等待AQS的锁队列加锁失败时的处理流程异步入队的机制总结ReentractLock如何设…

雨量监测站:守护大地的晴雨表

雨量监测站是一种专门用于测量和记录降雨量的设施。它通常由雨量计、数据采集器、传输装置和数据处理系统组成。雨量计负责感应雨滴的接触&#xff0c;通过一定的机制将降雨量转化为电信号或数字信号。数据采集器则负责收集这些信号&#xff0c;并将其传输至数据处理系统进行分…

FastAPI+vue3+Primeflex教学20240706,渲染阶乘案例

子绝父相 相对定位是相对于自己原本的位置定位。 绝对定位&#xff0c;如果父元素设置了相对定位&#xff0c;则相对于父元素进行绝对定位&#xff0c;否则相对于最近的设置了相对定位的元素进行绝对定位&#xff0c;或者相对于根元素进行绝对定位。 定位有四个方向&#xff0…

GitHub Copilot API

1. 引言 GitHub Copilot&#xff1a;智能编程的革新者 在软件开发的浩瀚宇宙中&#xff0c;GitHub Copilot犹如一颗璀璨的新星&#xff0c;以其独特的魅力引领着智能编程的新纪元。作为GitHub与OpenAI合作推出的革命性工具&#xff0c;Copilot不仅仅是一个简单的代码补全插件…

拉格朗日插值法【python,算法】

拉格朗日插值是一种在数值分析中用来构建通过一系列已知数据点的多项式插值的方法。这种方法以 18 世纪的法国数学家约瑟夫拉格朗日命名。当给定一组离散的数据点(&#x1d465;_0,&#x1d466;_0),(&#x1d465;_1,&#x1d466;_1),...,(&#x1d465;_&#x1d45b;,&…

38 IO流

目录 C语言的输入和输出流是什么CIO流stringstream的简单介绍 1. C语言的输入与输出 C语言中我们用到的最频繁的输出方式是scanf和printf&#xff0c;scanf&#xff1a;从标准输入设备&#xff08;键盘&#xff09;读取数据&#xff0c;并将值存在变量中。printf&#xff1a;…

JSP WEB开发(二) JavaBean

目录 JavaBean JavaBean特征 JavaBean的标签 JavaBean 的范围 标签 JavaBean JavaBean 是一种符合某些命名和设计规范的 Java 类&#xff0c;它是一种可重用组件技术&#xff0c;主要用于封装数据&#xff0c;执行负责的计算任务&#xff0c;封装事务逻辑等。JavaBean 的实…

高级计算机体系结构--期末教材复习

Chap2 性能评测和并行编程性能评测并行编程为什么需要三次 barrier改进方法 Chap3 互连网络交换和路由二维网格中 XY 路由 死锁、活锁及饿死死锁避免的方法&#xff1a;虚通道、转弯模型二维网格中最小 西向优先、北向最后和负向优先算法转弯模型&#xff1a;超立方体的部分自适…

安装 tesseract

安装 tesseract 1. Ubuntu-24.04 安装 tesseract2. Ubuntu-24.04 安装支持语言3. Windows 安装 tesseract4. Oracle Linux 8 安装 tesseract 1. Ubuntu-24.04 安装 tesseract sudo apt install tesseract-ocr sudo apt install libtesseract-devreference: https://tesseract-…

绝区贰--及时优化降低 LLM 成本和延迟

前言 大型语言模型 (LLM) 为各行各业带来了变革性功能&#xff0c;让用户能够利用尖端的自然语言处理技术处理各种应用。然而&#xff0c;这些强大的 AI 系统的便利性是有代价的 — 确实如此。随着 LLM 变得越来越普及&#xff0c;其计算成本和延迟可能会迅速增加&#xff0c;…

ctfshow web 36d 练手赛

不知所措.jpg 没啥用然后测试了网站可以使用php伪达到目的 ?filephp://filter/convert.base64-encode/resourcetest/../index.<?php error_reporting(0); $file$_GET[file]; $file$file.php; echo $file."<br />"; if(preg_match(/test/is,$file)){inclu…

如何处理 PostgreSQL 中由于表连接顺序不当导致的性能问题?

文章目录 一、理解表连接和连接顺序二、识别由于表连接顺序不当导致的性能问题三、影响表连接顺序的因素四、解决方案手动调整连接顺序创建合适的索引分析数据分布和优化查询逻辑 五、示例分析手动调整连接顺序创建索引优化查询逻辑 六、总结 在 PostgreSQL 中&#xff0c;表连…

uni-app优点有哪些?

uni-app的优点主要有以下几个方面&#xff1a; 跨平台开发&#xff1a;uni-app支持一套代码编写&#xff0c;多端运行&#xff0c;无需额外的适配工作&#xff0c;可以同时在iOS、Android、Web等多个平台上运行。这大大提高了开发效率&#xff0c;节省了开发成本和时间。统一的…

论文回顾 | CVPR 2021 | How to Calibrate Your Event Camera | 基于图像重建的事件相机校准新方法

论文速览 | CVPR 2021 | How to Calibrate Your Event Camera | 基于图像重建的事件相机校准新方法 1 引言 在计算机视觉和机器人领域,相机校准一直是一个基础而又重要的问题。传统的相机校准方法主要依赖于从已知校准图案中提取角点,然后通过优化算法求解相机的内参和外参。这…

Vue表单输入绑定v-model

表单输入绑定 在前端处理表单时&#xff0c;我们常常需要将表单输入框的内容同步给Javascript中相应的变量。手动连接绑定和更改事件监听器可能会很麻&#xff0c;v-model 指令帮我们简化了这一步骤。 <template><h3>表单输入绑定</h3><hr> <inpu…

Ubuntu基本环境配置

#Jdk 安装 #--查看 已安装 的jdk软件 java -version # 安装jdk软件(如果有选择请选 y) sudo apt install openjdk-11-jdk # 自行学习 vi 或 vim 学习网址如下&#xff1a; # https://www.runoob.com/linux/linux-vim.html #-- 修改系统级 path : /etc/profile 文件 (注意要…

ElasticSearch 如何计算得分及一个不太成熟的使用

1.背景 最近在做 ES 相关东西&#xff0c;只最会在查询的时候给不同的字段设置不同的权重&#xff0c;但是得分具体怎么算的不太明白&#xff0c;花了4-5 天研究和总结了一下。这样不至于被别人问到“这个分数怎么算出来的&#xff1f;”&#xff0c;两眼一抹黑&#xff0c;不…

【vue组件库搭建05】vitePress中使用vue/antd/demo预览组件

一、vitepress使用vue及antd组件 1.安装antd之后在docs\.vitepress\theme\index.ts引入文件 // https://vitepress.dev/guide/custom-theme import { h } from vue import type { Theme } from vitepress import DefaultTheme from vitepress/theme import ./style.css impor…

Vue进阶(四十五)Jest集成指南

文章目录 一、前言二、环境检测三、集成问题汇总四、拓展阅读 一、前言 在前期博文《Vue进阶&#xff08;八十八&#xff09;Jest》中&#xff0c;讲解了Jest基本用法及应用示例。一切顺利的话&#xff0c;按照文档集成应用即可&#xff0c;但是集成过程中遇到的问题可能五花八…