总结:
有一个良好的心态,积极的态度,并且看得开就不怕大部分的事情。
本周知识清单:
- 实现千问web页面
- 大模型微调操作步骤,背后机制和关键代码意思
-
文本微调和代码微调在数据集、微调脚本、结果衡量这3方面的区别
下周任务:
- 工作细则工作量调研
- codeqwen跑通
关键记录
实现千问web页面
官网:Qwen-VL/web_demo_mm.py at master · QwenLM/Qwen-VL · GitHub
github下载不了,好像太大了,就用了gitee,绑定了密钥啥的,大家搜索就能找到使用方法,最后是运行
git clone https://gitee.com/bishy/Qwen-VL1.git
才下载好
然后运行web_demo_mm.py文件
报错:RuntimeError: No CUDA GPUs are available,GPU不可用,在root路径服务器(而不是容器内)重启容器解决问题
docker restart 容器名称
记得重新启动ssh服务
/etc/init.d/ssh start
出现界面:
是没安装依赖环境导致的哈哈,离谱,居然忘了。
后面在qwen-vl目录下级联vscode,运行
pip install -r requirements.txt
后面就行了:
感觉还是有点傻
比较保守,很多新消息都说不知道。然后文件只能上传图片,没有之前问答复制功能,提交还需要按按钮
大模型微调操作步骤,背后机制和关键代码意思
(一)操作步骤
学习:【大模型开发 】 一文搞懂Fine-tuning(大模型微调)_finetuning大模型-CSDN博客
1.数据准备:
- 选择与任务相关的数据集。
- 对数据进行预处理,包括清洗、分词、编码等。
2.选择基础模型:
- 选择一个预训练好的大语言模型,如BERT、GPT-3等。
3.设置微调参数:
- 设定学习率、训练轮次(epochs)、批处理大小(batch size)等超参数。
- 根据需要设定其他超参数,如权重衰减、梯度剪切等。
4.微调流程:
- 加载预训练的模型和权重。
- 根据任务需求对模型进行必要的修改,如更改输出层。
- 选择合适的损失函数和优化器。
- 使用选定的数据集进行微调训练,包括前向传播、损失计算、反向传播和权重更新。
(二)背后机制
- 参数更新: 在微调过程中,不是对模型的所有参数进行随机初始化和重新训练,而是基于预训练模型已有的参数,只对部分参数进行调整。通常会选择与特定任务相关的层或模块的参数进行更新。
- 数据适配: 使用特定领域或任务的新数据来对模型进行训练。这些新数据与预训练模型所使用的大规模通用数据有所不同,具有更强的针对性。例如,对于情感分析任务,微调时使用的可能是带有情感标注的文本数据。
- 损失函数优化: 根据具体的微调任务定义合适的损失函数。例如,在分类任务中,常用交叉熵损失函数;在回归任务中,可能使用均方误差损失函数等。通过优化这个损失函数来调整模型的参数,使模型在新任务上的预测结果更加准确。
- 正则化: 为了防止过拟合,通常会采用一些正则化技术,如 L1 和 L2 正则化、Dropout 等。这有助于在微调时让模型学习到更具泛化能力的特征。
- 超参数调整: 像学习率、训练轮数、批大小等超参数需要根据新的数据和任务进行适当的调整。例如,如果数据量较小,可能需要较小的学习率和更多的训练轮数。
- 模型架构适应性: 某些情况下,可能需要对模型的架构进行一些小的修改,以更好地适应新任务的需求。但这种情况相对较少,因为预训练模型的架构通常具有较好的通用性。 举例来说,假设我们有一个预训练的语言模型用于一般的文本理解,当要将其微调用于机器翻译任务时,会使用平行语料(源语言和目标语言的对应文本对)作为新数据,重点调整与输出层相关的参数,并根据翻译任务的特点优化损失函数,同时注意正则化和超参数的选择,以使得模型能够学习到翻译的模式和规律。
(三)大型模型的经典网络结构-Transformer架构
来源:【大模型微调】一文掌握7种大模型微调的方法-CSDN博客
1.输入嵌入层(Input Embedding)
- 输入(Inputs):模型的输入环节,通常为单词或符号序列。
- 输入嵌入(Input Embedding):此步骤将输入序列(例如句中的每个单词)转化为嵌入表示,即能够表征单词语义信息的高维向量。
- 位置编码(Positional Encoding):鉴于Transformer不依赖序列,位置编码旨在提供序列中单词位置的信息,这些编码添加到输入嵌入中,确保模型即便同时处理输入也能够利用单词的顺序信息。
2.编码器层(Encoder,左边)
- Nx:指示有N个相同的编码器层叠加而成。每个编码器层包括两个主要子层:多头自注意力机制和前馈神经网络。
- 多头自注意力(Multi-Head Attention):注意力机制允许模型在处理每个单词时考虑到输入序列中的所有单词。多头部分表示模型并行学习输入数据的不同表示。
- 残差连接和归一化(Add & Norm):注意力层后面跟着残差连接和层归一化,有助于防止深层网络中的梯度消失问题,并稳定训练过程。
- 前馈神经网络(Feed Forward):全连接神经网络处理自注意力层的输出,包含两个线性变换和一个非线性激活函数。
3.解码器层(Decoder,右侧)
- 解码器亦包含多个相同的层,每层包括三个主要子层:掩蔽的多头自注意力机制、多头自注意力机制和前馈神经网络。
- 掩蔽多头自注意力(Masked Multi-Head Attention):与编码器的多头自注意力机制类似,但为确保解码顺序性,掩蔽操作确保预测仅依赖于之前的输出。
- 前馈神经网络(Feed Forward):与编码器相同,每个子层之后也有加法和归一化步骤。
4.输出嵌入层和输出过程
- 解码器端的嵌入层将目标序列转换为向量形式。
- 线性层(Linear)和Softmax层:解码器的输出通过线性层映射到一个更大的词汇空间,Softmax函数将输出转换为概率分布。
(四)大型模型微调的技术手段
监督微调(Supervised Fine-Tuning):它指的是在一个预训练的模型(如大型语言模型)基础上,通过提供标注好的数据进行进一步训练,以使模型在特定任务或领域上表现得更好。可参考:人工智能大语言模型微调技术:SFT 监督微调、LoRA 微调方法、P-tuning v2 微调方法、Freeze 监督微调方法-腾讯云开发者社区-腾讯云 (tencent.com)包括:
(1)全量微调(Full Fine-Tuning)
全量微调利用特定任务数据调整预训练模型的所有参数,以充分适应新任务。它依赖大规模计算资源,但能有效利用预训练模型的通用特征。
(2)参数高效微调(Parameter-Efficient Fine-Tuning, PEFT)
PEFT旨在通过最小化微调参数数量和计算复杂度,实现高效的迁移学习。它仅更新模型中的部分参数,显著降低训练时间和成本,适用于计算资源有限的情况。PEFT技术包括LoRA、QLoRA、适配器调整(Adapter Tuning)、前缀调整(Prefix Tuning)、提示调整(Prompt Tuning)、P-Tuning及P-Tuning v2等多种方法,可根据任务和模型需求灵活选择。
具体各种微调数学原理可以看上面提到的2个文章,写得都很好。
(五)代码突破
参考:Fine Tuning Qwen 1.5 for Coding (debuggercafe.com)
文件很大704M,而且在谷歌云,下载很慢。
基础模型:Qwen 1.5 0.5B
编码数据集: CodeAlpaca-20K
可在 Hugging Face 上使用。该数据集包含 20000 条代码,有编码相关指令、输入和输出,包含 Python、SQL 和 JavaScript 相关的提示。它们是高级长编码问题。有些是概念性问题,有些是编码问题,有些是输出相关的提示。
总的来说,这将教会我们的模型学习每种编码语言的基础知识,而不是使其成为高级编码器模型。
整个项目结构:
├── outputs
│ └── qwen_05b_code
│ ├── best_model
│ │ ├── added_tokens.json
│ │ ├── config.json
│ │ ├── generation_config.json
│ │ ├── merges.txt
│ │ ├── model.safetensors
│ │ ├── special_tokens_map.json
│ │ ├── tokenizer_config.json
│ │ └── vocab.json
│ └── logs
│ ├── checkpoint-20
│ ├── checkpoint-60
│ └── runs
├── inference.ipynb
├── qwen_05b_code.ipynb
└── requirements.txt
下载好文件,先装依赖:
pip install -r requirements.txts
具体需要:
- accelerate
- transformers
- trl
- datasets
- bitsandbytes
- peft
- tensorboard
qwen_05b_code.ipynb:
import os
import torch
from datasets import load_dataset
from transformers import (
AutoModelForCausalLM,
AutoTokenizer,
TrainingArguments,
pipeline,
logging,
BitsAndBytesConfig
)
from trl import SFTTrainer
from peft import LoraConfig
训练和数据集配置
接下来,我们定义训练和创建数据集所需的配置。
batch_size = 2 #批大小Batch size
num_workers = os.cpu_count() #用于数据加载的工作线程数Number of workers for data #loading
epochs = 10 #要训练的时期数Number of epochs to train for
bf16 = True
fp16 = False ##是否使用 BFloat16 或 Float16 混合精度
gradient_accumulation_steps = 256 #梯度累积步骤The gradient accumulation steps
context_length = 512 #序列长度The sequence length
learning_rate = 0.0001 #优化器的学习率Learning rate for the optimizer
model_name = 'Qwen/Qwen1.5-0.5B' #Hugging Face Qwen 模型仓库标签model repository tag
out_dir = 'outputs/qwen_05b_code' #输出目录output directory
加载并准备数据集
加载数据集并将其拆分为训练集和验证集:
dataset = load_dataset('sahil2801/CodeAlpaca-20k')#可能路径要改
full_dataset = dataset['train'].train_test_split(test_size=0.05, shuffle=True)
dataset_train = full_dataset['train']
dataset_valid = full_dataset['test']
print(dataset_train)
print(dataset_valid)
19020 training and 1002 validation samples
write a preprocessing function that will process the samples as necessary for our SFT Trainer pipeline.
编写一个预处理函数,该函数将根据 SFT Trainer 管道的需要处理样本。
def preprocess_function(example):
"""
Formatting function returning a list of samples (kind of necessary for SFT API).
"""
text = f"### Instruction:\n{example['instruction']}\n\n### Input:\n{example['input']}\n\n### Response:\n{example['output']}"
return text
load the Qwen model加载千问模型
if bf16:
model = AutoModelForCausalLM.from_pretrained(model_name).to(dtype=torch.bfloat16)
else:
model = AutoModelForCausalLM.from_pretrained(model_name)
print(model)
# Total parameters and trainable parameters.
total_params = sum(p.numel() for p in model.parameters())
print(f"{total_params:,} total parameters.")
total_trainable_params = sum(
p.numel() for p in model.parameters() if p.requires_grad)
print(f"{total_trainable_params:,} training parameters.")
以 BF16 或 FP16 混合精度加载模型。好久,2024.08.01日16:24开始运行。
66分26秒
以下是模型层和参数的数量:
加载分词器
tokenizer = AutoTokenizer.from_pretrained(
model_name,
trust_remote_code=True,
use_fast=False
)
初始化训练参数并训练模型
在训练之前,我们需要初始化训练参数和 SFT Trainer 管道
training_args = TrainingArguments(
output_dir=f"{out_dir}/logs",
evaluation_strategy='epoch',
weight_decay=0.01,
load_best_model_at_end=True,
per_device_train_batch_size=batch_size,
per_device_eval_batch_size=batch_size,
logging_strategy='epoch',
save_strategy='epoch',
num_train_epochs=epochs,
save_total_limit=2,
bf16=bf16,
fp16=fp16,
report_to='tensorboard',
dataloader_num_workers=num_workers,
gradient_accumulation_steps=gradient_accumulation_steps,
learning_rate=learning_rate,
lr_scheduler_type='constant',
)
trainer = SFTTrainer(
model=model,
train_dataset=dataset_train,
eval_dataset=dataset_valid,
max_seq_length=context_length,
tokenizer=tokenizer,
args=training_args,
formatting_func=preprocess_function,
packing=True
)
可视化来自数据加载器的一些样本:
dataloader = trainer.get_train_dataloader()
for i, sample in enumerate(dataloader):
print(tokenizer.decode(sample['input_ids'][0]))
print('#'*50)
if i == 5:
break
输出结果:
corners, a light shadow, and a maximum width of 500px.
### Input:
### Response:
.card {
border-radius: 10px;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
max-width: 500px;
}<|endoftext|>### Instruction:
Write a code snippet to remove all white spaces from a given string in
JavaScript.
### Input:
" Hello World! "
### Response:
let outputString = "Hello World!";
outputString = outputString.replace(/\s/g, ''); // removes white spaces
console.log(outputString);<|endoftext|>### Instruction:
Generate a list of all even numbers between 20 and 40.
### Input:
### Response:
even_numbers = []
for num in range(20, 41):
if num % 2 == 0:
even_numbers.append(num)
print(even_numbers)
# Output: [20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40]<|endoftext|>### Instruction:
Generate a python code that takes a list of integers, prints out an array
that is all True if the values are in the input list and all False otherwise.
### Input:
list_of_numbers = [5, 7, 10, 2]
通过调用train方法训练(要好久)
history = trainer.train()
训练后,将最佳模型保存到磁盘上。
model.save_pretrained(f"{out_dir}/best_model")
tokenizer.save_pretrained(f"{out_dir}/best_model")
以下是训练日志和验证损失图
在 epoch 3 上获得了最佳模型,这是我们在推理过程中将用于文本生成的模型。
使用训练好的千问模型进行推理
推理的代码位于:inference.ipynb
接下来的三个代码块导入必要的模块,加载模型和标记器,并初始化文本生成管道。
################import the necessary modules
from transformers import (
AutoModelForCausalLM,
logging,
pipeline,
AutoTokenizer
)
################load the model & the tokenizer
model = AutoModelForCausalLM.from_pretrained('outputs/qwen_05b_code/best_model/')
tokenizer = AutoTokenizer.from_pretrained('outputs/qwen_05b_code/best_model/')
################initialize the text generation pipeline
pipe = pipeline(
task='text-generation',
model=model,
tokenizer=tokenizer,
max_length=512,
device='cuda',
eos_token_id=tokenizer.eos_token_id
)
#初始化提示模板,并对模型进行前向传递
prompt = """### Instruction:
Write Python code for merge sort.
### Input:
### Response:
"""
result = pipe(
prompt
)
print(result[0]['generated_text'])
prompt=那一行提示它编写 Python 中的合并排序代码。
对比结果:
第一个显示代码微调的 Qwen 模型的输出,第二个显示通用聊天模型的输出。
# OUTPUT FROM CODE FINE-TUNED QWEN 1.5 MODEL.
def merge_sort(arr):
if len(arr) > 1:
mid = len(arr)//2
left = arr[:mid]
right = arr[mid:]
merge_sort(left)
merge_sort(right)
i = j = k = 0
while i < len(left) and j < len(right):
if left[i] < right[j]:
arr[k] = left[i]
i+=1
else:
arr[k] = right[j]
j+=1
k+=1
while i < len(left):
arr[k] = left[i]
i+=1
k+=1
while j < len(right):
arr[k] = right[j]
j+=1
k+=1
# OUTPUT FROM DEFAULT QWEN 1.5 CHAT MODEL.
def merge_sort(arr):
if len(arr) <= 1:
return arr
mid = len(arr) // 2
left_half, right_half = merge_sort(arr[:mid]), arr[mid:]
left_half.extend(left_half[:mid])
right_half.extend(right_half[mid:])
return merge(left_half, right_half)
def merge(left, right):
result = []
i = j = 0
while i < len(left) and j < len(right):
if left[i] > right[j]:
result.append(left[i])
i += 1
else:
result.append(right[j])
j += 1
while i < len(left):
result.append(left[i])
while j < len(right):
result.append(right[j])
return result
默认的 Qwen 聊天模型生成的合并排序代码不正确。但是,我们微调的模型会产生正确的输出。
SQL编码例子:
prompt = """### Instruction:
Write an SQL query to find the students who have a GPA of exactly 5 and have the name 'Goerge Russel'. Check for both first name and last name of 'George Russel'.
### Input:
### Response:
"""
result = pipe(
prompt
)
print(result[0]['generated_text'])
编写一个 SQL 查询,查找 GPA 正好为 5 且名称为“Goerge Russel”的学生。检查“George Russel”的名字和姓氏
# OUTPUT FROM CODE FINE-TUNED QWEN 1.5 MODEL.
SELECT * FROM students WHERE first_name = 'George' AND last_name = 'Russel' AND gpa = 5;
# OUTPUT FROM DEFAULT QWEN 1.5 CHAT MODEL.
SELECT s.name, s.first_name, s.last_name
FROM students s
WHERE s.gPA = 5 AND s.first_name = 'George Russel';
文本微调和代码微调在数据集、微调脚本、结果衡量这3方面的区别
数据集方面:
对于文本微调,数据集通常是大量的文本数据,涵盖各种主题和领域,例如新闻文章、小说、学术论文、社交媒体帖子等。这些数据的目的是让模型更好地理解和生成自然语言文本。 而代码微调的数据集则主要是各种编程语言的代码片段,包括完整的程序、函数、类等。这些代码通常来自开源项目、代码库或者特定的编程任务。感觉结构差不多,基本就是输入输出以及描述3方面。
(1)文本数据集格式:
如果训练数据中增加字段了system或history,别忘了dataset_info.json中的columns中也要增加 “system”: "system"或 “history”: “history”
dataset_info.json:
{
"train": {
"file_name": "train.json",
"columns": {
"prompt": "instruction",
"query": "input",
"response": "output"
}}
}
#这个文件是用来加载训练数据的配置文件,格式就是这个样子如果想要替换训练数据new_train.json那么格式如下:
{
"new_train": {
"file_name": "new_train",
"columns": {
"prompt": "instruction",
"query": "input",
"response": "output"
}}
}
#columns中的值如果训练数据不变也不需要变,那么训练数据格式什么样子呢
train.json:
[
{
"instruction": "我们如何在日常生活中减少用水?",
"input": "",
"output": "1. 使用节水装置,如节水淋浴喷头和水龙头。 \n2. 使用水箱或水桶收集家庭废水,例如洗碗和洗浴。 \n3. 在社区中提高节水意识。 \n4. 检查水管和灌溉系统的漏水情况,并及时修复它们。 \n5. 洗澡时间缩短,使用低流量淋浴头节约用水。 \n6. 收集雨水,用于园艺或其他非饮用目的。 \n7. 刷牙或擦手时关掉水龙头。 \n8. 减少浇水草坪的时间。 \n9. 尽可能多地重复使用灰水(来自洗衣机、浴室水槽和淋浴的水)。 \n10. 只购买能源效率高的洗碗机和洗衣机。"
},
{
"instruction": "编辑文章,使其更吸引读者。",
"input": "自主机器人是计算机控制的机器,被编程执行特定任务而不需要任何人类输入。自主机器人在各个行业中被越来越广泛地应用,从制造业到医疗保健再到安全。",
"output": "自主机器人是计算机控制的机器,被编程执行特定任务而不需要任何人类输入,从而实现了新的效率、精确度和可靠性水平。自主机器人在各个行业中被越来越广泛地应用,从制造业,它们可以使用精度和一致的质量组装复杂的组件,到医疗保健,可以协助进行医疗测试和处理,再到安全,可以监控大面积地区,保障人们和财产的安全。自主机器人还可以减少在危险或有害环境中的错误和增加安全,在工业流程的检查或维修期间等。由于其多样性,自主机器人将彻底改变我们工作方式的方式,使任务变得更加简单、快速,最终更加愉悦。"
},
{
"instruction": "政府可以采取哪些策略来减少空气污染?",
"input": "",
"output": "1. 实施强制的车辆排放标准和基于激励的计划,以降低车辆的碳足迹。\n2. 增加公共交通工具,减少公众对车辆的依赖。\n3. 增加对空气污染的影响的认识,鼓励市民减少污染物的生成。\n4. 投资于可再生能源的研究和开发,如太阳能和风能。\n5. 在工厂和发电厂安装空气污染控制装置,例如洗涤器。\n6. 对车辆和工厂使用清洁燃料。\n7. 实施更好的城市规划和控制拓展。\n8. 改善农业效率,减少化肥和杀虫剂的使用。\n9. 种植更多的树木以减少空气污染。\n10. 减少木材、煤炭和生物质的燃烧。"
},
{
"instruction": "可再生能源的存在对环境有什么影响?",
"input": "",
"output": "可再生能源的存在可以帮助减少空气污染和温室气体排放,因为它们几乎不会排放二氧化碳、二氧化硫等空气污染物。此外,使用可再生能源可以促进能源效率的进一步提高和能源利用的改善。可再生能源也可以帮助减少对化石燃料的依赖,这不仅可以减少排放,而且还可以帮助减少全球气候变化的风险。最后,可再生能源可以帮助保护自然资源,减少为了能源生产而开发更多土地和资源的需要。"
},
{
"instruction": "解释神经网络如何学习。",
"input": "",
"output": "神经网络是一种机器学习算法,它使用连接的节点集合来近似可以将输入变量映射到输出的函数。为了学习神经网络的参数,计算机需要调整节点之间连接的权重,以便网络为给定输入产生正确的输出。这个调整过程称为学习,通过比较网络产生的输出和期望的结果,然后使用优化算法来调整权重,使得网络输出逼近期望的结果。这个过程在多个输入和期望的输出上重复进行多次迭代。最终,连接节点之间的权重将被调整,以便神经网络的输出与期望的结果相匹配,学习过程将完成。"
},
{
"instruction": "给出一个机器学习算法的例子,并解释它是如何工作的。",
"input": "",
"output": "一个流行的机器学习算法的例子是支持向量机(SVM)。它是一个用于分类和回归任务的监督学习算法。它通过在n维空间中绘制数据点,由空间中的决策边界或超平面进行分离。该算法使用最大边距,这些边距尽可能远离两类数据点。这些边距有助于创建最优的决策超平面。然后,算法通过考虑分类任务中发生的错误来调整决策超平面,并相应地修改超平面。\n\n最终,支持向量机可以使用最优的决策超平面执行分类任务,预测数据点的类别。"
}]
(2)分类问题数据集:
zh_cls_fudan-news · 数据集 (modelscope.cn)
zh_cls_fudan-news由几千条数据,每条数据包含text、category、output三列:
- text 是训练语料,内容是书籍或新闻的文本内容
- category 是text的多个备选类型组成的列表
- output 则是text唯一真实的类型
(3)代码数据集
编码数据集: CodeAlpaca-20K
可在 Hugging Face 上使用。该数据集包含 20000 条代码,有编码相关指令、输入和输出,包含 Python、SQL 和 JavaScript 相关的提示。它们是高级长编码问题。有些是概念性问题,有些是编码问题,有些是输出相关的提示。
总的来说,这将教会我们的模型学习每种编码语言的基础知识,而不是使其成为高级编码器模型。
逐步生成ptomo代码数据集:
wickes1/pyomo-100 · Datasets at Hugging Face
微调脚本方面:
在文本微调中,微调脚本可能会更侧重于处理自然语言的特征,如词法分析、句法分析、语义理解等。可能会使用一些自然语言处理的技术和库,如 NLTK、SpaCy 等。
对于代码微调,微调脚本则需要考虑编程语言的语法规则、代码结构、变量命名等特点。可能会用到与代码分析和处理相关的工具和库,如 AST(抽象语法树)解析库等。
结果衡量方面:
文本微调的结果通常通过一些自然语言处理的指标来衡量,比如准确率、召回率、F1 值用于文本分类任务;困惑度用于语言模型评估;BLEU、ROUGE 等用于文本生成的评估。 在代码微调中,衡量结果可能会包括代码的准确性(是否能正确执行并产生预期结果)、代码的质量(遵循编程规范、代码风格等)、代码的复杂性(例如圈复杂度等指标)。 例如,对于一个文本情感分类的微调任务,如果微调后的模型在测试集上的准确率从 80%提高到 85%,说明微调取得了较好的效果。 而对于一个代码生成的微调任务,如果生成的代码能够成功编译并且在特定的测试用例中运行正确,并且代码的风格和结构符合一定的标准,那么可以认为微调是成功的。
每天一些linux操作小知识
重启容器之后级联vscode
换了公司电脑,得重新启动,重新级联vscode,级联vscode一直报错
输密码是对的,但是一直在输,到后面都怀疑自己密码是不是错的,后面找赖老师解决,原来是重启容器之后,还得重启ssh服务,在服务器内输入:
/etc/init.d/ssh start
后面更新一下就可以了,具体可以参考AI算法工程师实习周记(一)-CSDN博客
或者级联vscode主要参考vscode通过ssh连接服务器(吐血总结)_vscode ssh-CSDN博客
sudo: command not found 的解决方法:
参照这一篇:sudo: command not found 的解决方法-CSDN博客
发现只要在容器里这种命令不存在的解决方法都是以下代码换个名字而已。
运行:
apt-get install sudo
就好了
还得把之前的搬过去
比如funasr需要ffmpeg,运行:
sudo apt install ffmpeg
github上下载项目:
git clone url
url替换成项目网址,就是下图绿色按钮点击,然后红框复制
如果很慢可以用gitee。
新机子上运行get clone报错,没有get命令,运行apt-get install get报错E: Unable to locate package get,运行sudo apt-get update,过了一会儿没啥用。
注意:别打错是git不是get
报错:error: RPC failed; curl 92 HTTP/2 stream 0 was not closed cleanly: CANCEL (err 8) error: 7768 bytes of body are still expected
还是不行,最后用了gitee
git clone https://gitee.com/bishy/Qwen-VL1.git
成功了