LLM - DataCollatorForLanguageModeling 样本生成 by transformers

目录

一.引言

二.生成样本 By API

1.样本处理样式

2.DataCollatorForLanguageModeling

2.1 样本准备

2.2 API 生成

三.生成样本 By DIY

1.样本准备

2.data_colloator 实现

3.使用自定义 data_colloator

四.总结


一.引言

前面我们讲了 Baichuan7B 的 lora 微调步骤,我们在 QA 基础上构建了样本集并训练,但是细心的同学肯定发现我们原始样本中只给出了 input_ids 但是没有给出 labels,本文我们简单看下 data_collator 如何生成样本 label 并自定义实现一个简单的 data_collator。

二.生成样本 By API

1.样本处理样式

def preprocess(tokenizer, config, example, max_seq_length, prompt_key, target_key):prompt = example[prompt_key]target = example[target_key]prompt_ids = tokenizer.encode(prompt, max_length=max_seq_length, truncation=True)target_ids = tokenizer.encode(target, max_length=max_seq_length, truncation=True, add_special_tokens=False)# 最终还是将 instruction 的输入输出都拼在一起,使用经典的 causal-LM 的 next word prediction 方式来训练input_ids = prompt_ids + target_ids + [config.eos_token_id] # EOS 用于标识句子结束return {"input_ids": input_ids, "seq_len": len(prompt_ids)}

首先加载 tokenizer 对 Q 和 A 分别 token 获取对应 Q_ids 和 A_ids:

Q: 请计算:39 * 0 = 什么?
A: 这是简单的乘法运算,39乘以0得到的是0
TokenQ: [31106, 15875, 77, 57, 53, 31159, 53, 60, 58, 31135, 6787, 6775, 81]
TokenA: [31106, 3908, 14313, 31640, 31257, 31481, 31742, 72, 57, 53, 31640, 31187, 53, 60, 58, 9323, 31178, 52, 79, 54, 59, 56]

获取 ids 后,会直接将 Q_ids A_ids 连接并在尾部增加 eos_token_id 标识当前句子结束,这里 eos_token_id = 2,合并后的 input_ids 如下:

input_ids = [31106, 15875, 77, 57, 53, 31159, 53, 60, 58, 31135, 6787, 6775, 81, 31106, 3908, 14313, 31640, 31257, 31481,31742, 72, 57, 53, 31640, 31187, 53, 60, 58, 9323, 31178, 52, 79, 54, 59, 56, 2]

除此之外,json 里还用 seq_len 记录了 prompt_ids 即 Q_ids 的长度:

json = {"input_ids": input_ids, "seq_len": 13}

2.DataCollatorForLanguageModeling

data_collator = DataCollatorForLanguageModeling(tokenizer=tokenizer,mlm=False)
    # 初始化 trainer, 此处报错: NotImplementedError: Cannot copy out of meta tensor; no data!trainer = ModifiedTrainer(model=model,train_dataset=dataset,args=training_args,callbacks=[TensorBoardCallback(writer)], # 回调将训练情况写入 tensorboarddata_collator=data_collator,)trainer.train()

上文中我们把 json 样本生成的 Dataset 和 DataCollatorForLanguageModeling 直接传给了 Trainer 训练,但是样本中并没有 labels,于是就在想没有 labels 怎么梯度回传,下面用 DataCollatorForLanguageModeling API 看下 data_collator 使用后生成的数据样式。

2.1 样本准备

这里我直接将第一步 tokenizer 后的样本手动生成两个 json 测试后续流程:

# p: [31106, 15875, 77, 57, 53, 31159, 53, 60, 58, 31135, 6787, 6775, 81]
# t: [31106, 3908, 14313, 31640, 31257, 31481, 31742, 72, 57, 53, 31640, 31187, 53, 60, 58, 9323, 31178, 52, 79, 54, 59, 56]
sample1 = [31106, 15875, 77, 57, 53, 31159, 53, 60, 58, 31135, 6787, 6775, 81, 31106, 3908, 14313, 31640, 31257, 31481,31742, 72, 57, 53, 31640, 31187, 53, 60, 58, 9323, 31178, 52, 79, 54, 59, 56, 2]# p: [31106, 33370, 5629, 16927, 54, 56, 31179, 11002, 72, 31526, 31342, 8835, 31221, 31423, 7156, 55, 31396, 31222, 33370, 31604, 72, 31415, 31396, 31222, 33370, 1231, 31221, 31195, 6851, 11002, 75]
# t: [31106, 33370, 5629, 16927, 54, 56, 31179, 11002, 72, 8835, 31221, 31423, 55, 31396, 31222, 33370, 31604, 72, 2926, 31415, 31396, 31222, 33370, 1231, 31221, 11254, 11002, 31380, 1522, 31482, 11002, 31380, 31640, 31187, 31222, 33370, 31135, 31396, 31380, 73, 5, 54, 56, 34399, 55, 31191, 60, 5, 31415, 31396, 31222, 33370, 1231, 31221, 31195, 60, 31179, 11002, 73, 2122, 72, 6787, 31161, 31415, 31396, 31222, 33370, 1231, 31221, 31195, 60, 31179, 11002, 73]
sample2 = [31106, 33370, 5629, 16927, 54, 56, 31179, 11002, 72, 31526, 31342, 8835, 31221, 31423, 7156, 55, 31396,31222, 33370, 31604, 72, 31415, 31396, 31222, 33370, 1231, 31221, 31195, 6851, 11002, 75, 31106, 33370, 5629,16927, 54, 56, 31179, 11002, 72, 8835, 31221, 31423, 55, 31396, 31222, 33370, 31604, 72, 2926, 31415, 31396,31222, 33370, 1231, 31221, 11254, 11002, 31380, 1522, 31482, 11002, 31380, 31640, 31187, 31222, 33370, 31135,31396, 31380, 73, 5, 54, 56, 34399, 55, 31191, 60, 5, 31415, 31396, 31222, 33370, 1231, 31221, 31195, 60,31179, 11002, 73, 2122, 72, 6787, 31161, 31415, 31396, 31222, 33370, 1231, 31221, 31195, 60, 31179, 11002,73, 2]json1 = {"input_ids": sample1, "seq_len": 13}
json2 = {"input_ids": sample2, "seq_len": 31}features = [json1, json2]

每个 json 的 input_ids 都遵循 Q_ids + A_ids + [SEP] 即 Prompt_ids + Target_ids + [SEP] 的规则生成。

2.2 API 生成

from transformers import AutoTokenizer
from transformers import DataCollatorForLanguageModelingmodel_checkpoint = "/model/baichuan-7B"
tokenizer = AutoTokenizer.from_pretrained(model_checkpoint, trust_remote_code=True)
tokenizer.pad_token = tokenizer.unk_token
data_collator = DataCollatorForLanguageModeling(tokenizer=tokenizer,mlm=False)features = [json1, json2]
batch = data_collator(features)print(batch)

调用 API 生成一个 Batch 对应的大 json 共包含 4 个 key:

• attention_mask

对于基于 mask 的语言任务例如 Bert,data_collator 可以帮助生成掩码标签。对于 sample1 其长度较短,所以后面的 PAD_TOKEN 部分的 mask 均为 0,而 sample2 的长度为所有样本中最长的且小于 max_length,所以其 mask 均为 1。

'attention_mask': tensor([[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, 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, 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, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],[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, 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, 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, 1, 1, 1,1, 1, 1, 1, 1, 1, 1, 1, 1, 1]])

• input_ids

与上面同理,data_collator 会就算当前 batch 样本中的 max_length,对于不足 max_length 的样本进行补齐的 padding 操作,所以 sample1 的样本补了很多 padding,sample2 正常。

'input_ids': tensor([[31106, 15875,    77,    57,    53, 31159,    53,    60,    58, 31135,6787,  6775,    81, 31106,  3908, 14313, 31640, 31257, 31481, 31742,72,    57,    53, 31640, 31187,    53,    60,    58,  9323, 31178,52,    79,    54,    59,    56,     2,     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,     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,     0,     0,0,     0,     0,     0,     0,     0],[31106, 33370,  5629, 16927,    54,    56, 31179, 11002,    72, 31526,31342,  8835, 31221, 31423,  7156,    55, 31396, 31222, 33370, 31604,72, 31415, 31396, 31222, 33370,  1231, 31221, 31195,  6851, 11002,75, 31106, 33370,  5629, 16927,    54,    56, 31179, 11002,    72,8835, 31221, 31423,    55, 31396, 31222, 33370, 31604,    72,  2926,31415, 31396, 31222, 33370,  1231, 31221, 11254, 11002, 31380,  1522,31482, 11002, 31380, 31640, 31187, 31222, 33370, 31135, 31396, 31380,73,     5,    54,    56, 34399,    55, 31191,    60,     5, 31415,31396, 31222, 33370,  1231, 31221, 31195,    60, 31179, 11002,    73,2122,    72,  6787, 31161, 31415, 31396, 31222, 33370,  1231, 31221,31195,    60, 31179, 11002,    73,     2]])

Tips:

这里 pad 的 0 和 mask 的 0 需要区分,这里 padding 为 0 是因为我们定义了 pad_token = unk_token,而 unk_token = <unk> 经过 tokenizer encode 后得到的是 [0]。

code=tokenizer.encode(tokenizer.pad_token, max_length=10000, truncation=True)
print('pad', tokenizer.unk_token, 'token', code)
=> pad <unk> token [0]

• seq_len

这个很好理解,一个 batch 内的多个样本,每个样本的 prompt_id 的长度即 Q_id 的长度。这个长度主要用于 batch 内判断 longest 最长的序列是多长,从而对短的样本进行 padding,保证进入深度模型网络的样本维度一致。

'seq_len': tensor([13, 31])

• labels

'labels': tensor([[31106, 15875,  77,  57,  53, 31159,  53,  60,    58, 31135,6787,  6775,    81, 31106,  3908, 14313, 31640, 31257, 31481, 31742,72,    57,    53, 31640, 31187,    53,    60,    58,  9323, 31178,52,    79,    54,    59,    56,     2,  -100,  -100,  -100,  -100,-100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,-100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,-100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,-100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,-100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,-100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,  -100,-100,  -100,  -100,  -100,  -100,  -100],[31106, 33370,  5629, 16927,    54,    56, 31179, 11002,    72, 31526,31342,  8835, 31221, 31423,  7156,    55, 31396, 31222, 33370, 31604,72, 31415, 31396, 31222, 33370,  1231, 31221, 31195,  6851, 11002,75, 31106, 33370,  5629, 16927,    54,    56, 31179, 11002,    72,8835, 31221, 31423,    55, 31396, 31222, 33370, 31604,    72,  2926,31415, 31396, 31222, 33370,  1231, 31221, 11254, 11002, 31380,  1522,31482, 11002, 31380, 31640, 31187, 31222, 33370, 31135, 31396, 31380,73,     5,    54,    56, 34399,    55, 31191,    60,     5, 31415,31396, 31222, 33370,  1231, 31221, 31195,    60, 31179, 11002,    73,2122,    72,  6787, 31161, 31415, 31396, 31222, 33370,  1231, 31221,31195,    60, 31179, 11002,    73,     2]])}

最后一个 key 是 labels,这里也可以解决我们前面的疑惑了,为什么样本里只有 input_ids 和 seq_len,但是经过 data_collator 处理送到 trainer 可以正常训练,这里的 label 对应的是 QA 里 A 的 token ids 即 target ids,以第一个 sample 为例,第一个 sample 的 A ids 为:

[31106, 3908, 14313, 31640, 31257, 31481, 31742, 72, 57, 53, 31640, 31187, 53, 60, 58, 9323, 31178, 52, 79, 54, 59, 56] + [2]

最后的 [2] 与前面 <unk> 类似,eos_token 后编码为 [2]:

code=tokenizer.encode(tokenizer.eos_token, max_length=10000, truncation=True)
print('eos', tokenizer.eos_token, 'token', code)
=> eos </s> token [2]

三.生成样本 By DIY

上面使用 Transformer API 实现了 {"input_ids":  xxx, "seq_len": xxx} 形式的数据解析与样本生成,下面我们参考上面逻辑自定义一版 data_collator。首先整理一下思路:

input_ids = Q_ids + A_ids + [SEP]_ids

seq_len = Q_ids.length

labels =  if (max_length) A_ids else A_ids + padding * n

根据 A_ids 的长度判断是否是 longest,然后决定是否补齐 padding 从而生成对应 Label。

1.样本准备

# p: [31106, 15875, 77, 57, 53, 31159, 53, 60, 58, 31135, 6787, 6775, 81]
# t: [31106, 3908, 14313, 31640, 31257, 31481, 31742, 72, 57, 53, 31640, 31187, 53, 60, 58, 9323, 31178, 52, 79, 54, 59, 56]
sample1 = [31106, 15875, 77, 57, 53, 31159, 53, 60, 58, 31135, 6787, 6775, 81, 31106, 3908, 14313, 31640, 31257, 31481,31742, 72, 57, 53, 31640, 31187, 53, 60, 58, 9323, 31178, 52, 79, 54, 59, 56, 2]# p: [31106, 33370, 5629, 16927, 54, 56, 31179, 11002, 72, 31526, 31342, 8835, 31221, 31423, 7156, 55, 31396, 31222, 33370, 31604, 72, 31415, 31396, 31222, 33370, 1231, 31221, 31195, 6851, 11002, 75]
# t: [31106, 33370, 5629, 16927, 54, 56, 31179, 11002, 72, 8835, 31221, 31423, 55, 31396, 31222, 33370, 31604, 72, 2926, 31415, 31396, 31222, 33370, 1231, 31221, 11254, 11002, 31380, 1522, 31482, 11002, 31380, 31640, 31187, 31222, 33370, 31135, 31396, 31380, 73, 5, 54, 56, 34399, 55, 31191, 60, 5, 31415, 31396, 31222, 33370, 1231, 31221, 31195, 60, 31179, 11002, 73, 2122, 72, 6787, 31161, 31415, 31396, 31222, 33370, 1231, 31221, 31195, 60, 31179, 11002, 73]
sample2 = [31106, 33370, 5629, 16927, 54, 56, 31179, 11002, 72, 31526, 31342, 8835, 31221, 31423, 7156, 55, 31396,31222, 33370, 31604, 72, 31415, 31396, 31222, 33370, 1231, 31221, 31195, 6851, 11002, 75, 31106, 33370, 5629,16927, 54, 56, 31179, 11002, 72, 8835, 31221, 31423, 55, 31396, 31222, 33370, 31604, 72, 2926, 31415, 31396,31222, 33370, 1231, 31221, 11254, 11002, 31380, 1522, 31482, 11002, 31380, 31640, 31187, 31222, 33370, 31135,31396, 31380, 73, 5, 54, 56, 34399, 55, 31191, 60, 5, 31415, 31396, 31222, 33370, 1231, 31221, 31195, 60,31179, 11002, 73, 2122, 72, 6787, 31161, 31415, 31396, 31222, 33370, 1231, 31221, 31195, 60, 31179, 11002,73, 2]json1 = {"input_ids": sample1, "seq_len": 13}
json2 = {"input_ids": sample2, "seq_len": 31}features = [json1, json2]

样本继续使用上面构造的 json1 和 json2 并统一放到 features 的 list 中。

2.data_colloator 实现

def data_collator(features: list) -> dict:# 序列长度: [36, 106]len_ids = [len(feature["input_ids"]) for feature in features]# 取最长的序列长度: 106longest = max(len_ids)input_ids = []labels_list = []# 降序排列for ids_l, feature in sorted(zip(len_ids, features), key=lambda x: -x[0]):ids = feature["input_ids"]  # tokenIdsseq_len = feature["seq_len"]  # seqLen# len(prompt) x [-100] + Target + [longest - len(prompt)] * [-100]labels = ([-100] * seq_len + ids[seq_len:] + [-100] * (longest - ids_l))ids = ids + [pad_token_id] * (longest - ids_l)_ids = torch.LongTensor(ids)labels_list.append(torch.LongTensor(labels))input_ids.append(_ids)# tensor([[], []])input_ids = torch.stack(input_ids)labels = torch.stack(labels_list)return {"input_ids": input_ids,"labels": labels,}

data_collator 的逻辑主要是这一句:

# len(prompt) x [-100] + Target + [longest - len(prompt)] * [-100]
labels = ([-100] * seq_len + ids[seq_len:] + [-100] * (longest - ids_l))

即将 Q mask 进行掩码,A 即 Target 保持不变,最后根据 longest 的长度决定是否 padding,这里手动指定了 pad_token_id = 0,实际代码中可以使用 tokenizer 自动指定:

tokenizer.pad_token_id

除此之外,这里和上面 API 生成还有一个区别是是否 mask Q_ids,API 把 Q_ids 全部去掉,上面方法保留了 Q_ids 的位置,但是使用 -100 进行了 mask,实际场景下二者没有区别,只不过 DIY 的 labels 如果 Q_ids 很长则会占用很多无关空间。

3.使用自定义 data_colloator

    trainer = ModifiedTrainer(model=model,train_dataset=dataset,args=training_args,callbacks=[TensorBoardCallback(writer)], # 回调将训练情况写入 tensorboarddata_collator=data_collator,)

定义好 Trainer 后,将上面定一个 data_collator 传给 data_collator 参数即可,不过常规情况下我们使用 API 即可,如果自己对样本和 label 的构建有自定义需求,则可以采用后者 DIY 的形式。

四.总结

经过上面的分析,对于样本的处理和 label 的生成流程我们大致清晰了,下面解释下上面的样本如何应用在 LM 大语言模型中以及自己理解的这样构造的含义。

input 为 QA,output 为 A。Input 和 Output 分别在 Embedding lookup 获取输入向量,添加 position 向量后进入 Multi-Head Attention,首先经过 Q、K、V 的 Linear 映射转换,随后经过 Encoder 和 Decoder 的 Transformer 结构,最终通过一个 Linear + Softmax 输出预测概率 logits,输出概率 logits 与 A_ids 对应的 multi_hot 向量计算 batch loss 并回传,这里会忽略 [-100] 的掩码,更完整的 loss 计算逻辑大家可以参考 model.loss 的实现。

    # 根据输入计算 Lossdef compute_loss(self, model, inputs, return_outputs=False):return model(input_ids=inputs["input_ids"],labels=inputs["labels"],).loss

一般情况下,这里 QA 也分别代表 Prompt 和 Target,上面这种样本和 label 的构造方式意在学习当给定 Prompt 的前提提示下,模型能够预测得到 Target,即语言生成。如果想要学习其他不同的模式,大家也可以根据需求自定义修改上面的 data_collator。

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

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

相关文章

详解sentinel使用

目录 1.概述 2.下载安装 3.应用托管 4.流量控制 4.1.流控规则 4.2.流控模式 4.2.1.直接模式 4.2.2.关联模式 4.2.3.链路模式 4.3.流控效果 4.3.1.预热 4.3.2.排队等待 5.降级 5.1.降级规则 5.2.降级策略 5.2.1.RT 5.2.2.异常比例 5.2.3.异常数 1.概述 senti…

直播 | SDS 容灾方案,让制品数据更安全

近日&#xff0c;腾讯 CODING WePack 制品管理系统 V1 以及腾讯 CODING DevOps 研发效能管理平台 V7 与 XSKY 星辰天合的统一数据平台 XEDP 及天合翔宇分布式存储系统完成互相兼容认证&#xff0c;在数据层面满足了共同客户敏捷开发的高可用建设合规要求。 联合解决方案可以帮…

【动手学深度学习】层和块

层和块 简单介绍 块&#xff1a;描述单个层&#xff0c;由多个层组成的组件或整个模型本身。使用块进行抽象的一个好处是可以将一些块组合成更大的组件&#xff0c;这一过程通常是递归的 简单入门 import torch from torch import nn from torch.nn import functional as F# …

【GitHub】腾讯这一款设计神器,开源了!PAG 动效组件

作为一个资深的互联网用户&#xff0c;我们经常会在各种产品上看到十分酷炫的动画效果。比如&#xff0c;短视频中有趣的虚拟场景、直播间粉丝打榜的 “火箭”、“轮船” 等等。 如今&#xff0c;优质的动效不仅可以使用户更容易地理解产品功能和操作方式&#xff0c;减少用户…

一套完全开源,支持多租户,界面配置单点的后端框架JVS

JVS的多租户体系统 在IT系统中&#xff0c;“租户”&#xff08;tenant&#xff09;通常用于指代一种多租户架构&#xff08;multi-tenancy&#xff09;&#xff0c;它是一种软件架构模式&#xff0c;允许多个用户或组织共享相同的应用程序或系统实例&#xff0c;但彼此之间的…

lwip-2.1.3自带的httpd网页服务器使用教程(一)从SD卡读取网页文件并显示

概述 本教程使用的单片机是STM32F103ZE&#xff0c;有线网口芯片为ENC28J60。 本教程里面的网页由于需要兼容Windows XP系统的IE8浏览器&#xff0c;所以采用HTML 4.01编写&#xff0c;不使用任何前端框架。笔者使用的网页设计软件是Adobe Dreamweaver CS3。 开发板PCB文件是公…

运维小知识(一)——centos系统安装(小白入门级)

目录 1.制作系统U盘 2.安装centos系统 3.系统配置 3.1【语言】配置​编辑 3.2【软件选择】配置 3.3【安装位置】配置 3.4【主机名、root密码、网络】配置 1.制作系统U盘 首先下载软件ventoy&#xff0c;制作系统U盘&#xff0c;买个新U盘。先在笔记本电脑安装ventoy软件&a…

产品经理学习画原型(三)

1.布尔运算的使用 合并必须选择两个及以上元件 合并后&#xff1a; 组合&#xff1a; 去除顶层&#xff1a;

常用API学习01(Java)

Math Math是一个帮助我们用于进行数学计算的工具类。私有化的构造方法&#xff0c;所有方法都是静态的。 Math类的常用方法&#xff1a; public static int abs(int a) 获取参数绝对值 public static double cell(double a) 向上取整 public static double floor(…

全链路Python环境迁移

全链路Python环境迁移 在当前的Python环境中&#xff0c;安装一些库以后&#xff0c;如果换了一套Python环境&#xff0c;难道再来一次不停的pip install&#xff1f;当然不是。 第一步&#xff0c;使用pip freeze&#xff08;冻结&#xff09;备份当前Python库的环境 pip f…

linux 服务器之间传输文件的方式

情景&#xff1a;有时迁移项目&#xff0c;一般人就想到需要在服务器下载到win本地电脑上面&#xff0c;再上传到目的服务器&#xff0c;这样若是文件大&#xff0c;下载的速度都足够让你歇一天了。遇到这问题&#xff0c;怎么解决呢&#xff1f; 方法1&#xff1a;scp 【优点…

《向量数据库指南》——传统数据库上的向量搜索插件

传统数据库上的向量搜索插件 很好,现在我们已经知道了向量搜索库和向量数据库之间的区别,下面让我们来看看向量数据库与向量搜索插件有何不同。 很多传统关系型数据库和搜索系统,如 ClickHouse 和 Elasticsearch,都包含内置的向量搜索插件。例如,Elasticsearch 8.0 包…