0%


在使用 UniVpn 进行 SSL VPN 连接时,为了确保网络连接的稳定性和可靠性,您可能需要启用自动重连功能。该功能可以在 VPN 连接意外中断时自动重新建立连接,从而减少因网络中断带来的不便。本文将介绍如何在 Linux 操作系统下,通过结合 expect 脚本和 ping 探测来实现自动重连功能。

环境准备

以 UniVpn 为例,我们将通过以下步骤实现自动重连:

启动 VPN 客户端

首先,在 shell 命令行中运行以下命令来启动 UniVpn,并创建一个 VPN 连接:

1
/usr/local/UniVPN/serviceclient/UniVPNCS

编写 expect 脚本

由于需要自动处理 VPN 连接,您需要安装 expect 程序。该工具能够自动化与命令行交互的操作。

安装 expect

1
apt install expect

然后,编写一个 expect 脚本(例如 univpn_run.sh),用于监控并自动重连 VPN。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#!/bin/bash
while true
do
expect <<EOF
set timeout -1
spawn /usr/local/UniVPN/serviceclient/UniVPNCS

# 等待欢迎信息
expect "Welcome to UniVPN"
send "3\r"

# 等待连接选项
expect "*1:Connect*"
send "1\r"

# 等待连接成功提示
expect "*Please input the login user name*"
send "[username]\r" #这里输入vpn用户名

# 等待输入密码提示
expect "*Please input the login user password*"
send "[password]\r" #这里输入vpn密码

# 等待最终连接成功提示
expect "*Connect Success,Enjoy*"

spawn sh ./testping.sh #这里是一个探测ping的代码
expect "*IP testing error*"

send "q\n"
expect "*Logout succeeded.*"

EOF

sleep 2
done

编写 ping 探测脚本

接下来,编写一个用于检测网络连通性的 ping 脚本(例如 testping.sh)。该脚本会定期检测 VPN 连接是否正常,若检测到连接中断,则会触发自动重连。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/bash
while true
do
# 要ping的IP地址
IP_ADDRESS="xxx.xxx.xxx.xxx" #vpn连接上以后能ping通的一个ip

# 执行ping命令,检查IP地址是否可达
ping -c 1 $IP_ADDRESS > /dev/null 2>&1

# 检查ping命令的退出状态
if [ $? -eq 0 ]; then
echo "IP testing success" #如果ping通了,输出
else
echo "IP testing error" #如果ping不通了,输出
exit
fi
sleep 20 #每20秒ping一次
done

执行自动重连

最后,执行以下命令运行自动重连脚本:

1
2
chmod +x univpn_run.sh testping.sh &  ./univpn_run.sh

该脚本将持续检测网络状态,若 ping 不通,则会结束当前 VPN 连接并尝试重新连接。

注意事项

在多次连接后,可能会出现 VPN 无法正常连接的情况,这通常是由于网卡问题导致的。为解决这一问题,您可以编写一个脚本,在探测到网络故障后,自动重启网络服务。

此外,若重启网络服务后某些依赖网络的服务(如 Docker)出现问题,您可以在脚本中加入这些服务的重启命令。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/bin/bash

# crontab设置: 30分钟执行一次检查
# */30 * * * * /root/dashboard/v2-web/docs/network_check.sh

# 目标IP地址
TARGET_IP="127.0.0.1" #这里换成你的IP地址

# 使用ping命令连续ping指定次数(例如每10秒一次,共ping 3次)
COUNT=1 #这里探测多少次
INTERVAL=10 #这是每次探测的间隔时间

# 使用ping命令进行测试
RESULT=$(ping -c $COUNT -i $INTERVAL $TARGET_IP | grep 'Destination Host Unreachable')

# 如果ping的结果包含"Destination Host Unreachable"
if [[ "$RESULT" != "" ]]; then
echo "$(date) - Ping to $TARGET_IP failed. Restarting network service..."

# 使用systemctl命令重启网络服务
systemctl restart network
#systemctl restart docker #这里是因为重启了network以后,docker的网络会出现问题,所以就重启一下docker。如果你有其他服务也可以这样重启一下。

fi
exit 0

定时检测

为了确保 VPN 的稳定性,您可以将上述脚本与定时任务(如 cron)结合,定期执行 ping 探测,确保在网络异常时及时恢复连接。


通过上述步骤,您可以在 Linux 操作系统下实现 UniVpn 的自动重连功能,从而提升网络连接的稳定性和可靠性。


CNN 是什么?

在机器学习中,分类器将类标签分配给数据点。例如,图像分类器为图像中存在的对象产生一个类标签(例如鸟、飞机)。卷积神经网络(CNN)是一种类型的分类器,擅长解决这个问题!

CNN是一种神经网络:用于识别数据中的模式的算法。神经网络通常由一组神经元组成,这些神经元组织成层,每层都有自己可学习的权重和偏差。让我们将CNN分解为多个基本构建模块。

  1. 一个张量可以被视为一个n维矩阵。在上述CNN中,张量将是三维的,除了输出层。
  2. 一个神经元可以被视为一个接受多个输入并产生单个输出的函数。神经元的输出在上面被表示为红色→蓝色的激活图。
    一个层简单地是具有相同操作的神经元的集合,包括相同的超参数。
  3. 一个简单地是具有相同操作的神经元的集合,包括相同的超参数。
  4. 核权重和偏差,虽然对每个神经元都是独特的,但在训练阶段进行调整,并且允许分类器适应所提供的问题和数据集。它们在可视化中使用黄色→绿色的差异颜色刻度进行编码。具体的值可以通过点击神经元或悬停在卷积弹性解释视图中的核/偏差上来查看交互式公式视图中的。
  5. CNN表达了一个可微分的评分函数,这在输出层的可视化中表示为类别得分

如果您之前学习过神经网络,这些术语可能听起来很熟悉。那么CNN有何不同之处呢?CNN利用一种特殊类型的层,恰当地称为卷积层,使它们能够很好地学习图像和类似图像的数据。关于图像数据,CNN可用于许多不同的计算机视觉任务,如图像处理、分类、分割和目标检测

CNN Explainer中,您可以看到一个简单的CNN如何用于图像分类。由于网络的简单性,其性能并不完美,但这没关系!CNN Explainer中使用的网络架构Tiny VGG包含了如今最先进的CNN中使用的许多相同层和操作,但规模较小。这样,入门将会更容易理解。

每个网络层都有什么作用?

让我们逐层了解网络中的每一层。在阅读时,可以随意与可视化工具-CNN Explainer进行交互,点击和悬停在不同部分。

输入层(Input Layer)

输入层(最左边的层)代表CNN中的输入图像。因为我们使用RGB图像作为输入,输入层有三个通道,分别对应红色、绿色和蓝色通道,在这个层中显示。当您点击上面的网络详情图标时,使用颜色标尺显示详细信息(在这一层和其他层上)。

卷积层(Convolutional Layers)

卷积层是CNN的基础,因为它们包含了学习到的卷积核(权重),这些卷积核可以提取出区分不同图像的特征,这正是我们进行分类所需要的!当您与卷积层交互时,您会注意到前一层和卷积层之间的联系。每个连接代表一个独特的卷积核,用于卷积操作以生成当前卷积神经元的输出或激活图。

卷积神经元执行一个逐元素的点积运算,使用一个独特的卷积核和前一层对应的神经元的输出。这将产生与独特卷积核数量相同的中间结果。卷积神经元是所有中间结果与学习到的偏置求和的结果。

例如,让我们看一下上面Tiny VGG架构中的第一个卷积层。注意这一层有10个神经元,但前一层只有3个神经元。在Tiny VGG架构中,卷积层是全连接的,意味着每个神经元与前一层的每个神经元都有连接。关注第一个卷积层中最上面的卷积神经元的输出,当我们悬停在激活图上时,我们可以看到有3个独特的卷积核。


Figure 1. As you hover over the activation map of the topmost node from the first convolutional layer, you can see that 3 kernels were applied to yield this activation map. After clicking this activation map, you can see the convolution operation occuring with each unique kernel.

这些核的大小是由网络架构的设计者指定的超参数。为了产生卷积神经元(激活图)的输出,我们必须对上一层的输出和网络学习的唯一核进行逐元素点积运算。在TinyVGG中,点积运算使用1的步幅,这意味着每个点积中核都会移动1个像素,但这是网络架构设计者可以调整以更好地适应其数据集的超参数。我们必须对所有3个核执行此操作,这将产生3个中间结果。


Figure 2. The kernel being applied to yield the topmost intermediate result for the discussed activation map.

然后,执行元素级求和,其中包含所有3个中间结果以及网络学习的偏差。之后,生成的二维张量将是在上述界面中查看的第一个卷积层中最顶层神经元的激活图。必须应用相同的操作来生成每个神经元的激活图。

通过一些简单的数学运算,我们可以推断出在第一个卷积层中有3 x 10 = 30个独特的大小为3x3的卷积核。卷积层与前一层之间的连接是在构建网络架构时的设计决策,这将影响每个卷积层中的卷积核数量。

了解超参数(Hyperparameters)

Hyperparameters

  1. 填充(Padding) 通常在卷积核超出激活图时是必要的。填充可以保护激活图边缘的数据,提高性能,并有助于保持输入的空间大小,使架构设计师能够构建更深、性能更高的网络。存在许多填充技术,但最常用的方法是零填充,因为它具有性能好、简单和计算效率高的特点。该技术涉及在输入的边缘对称地添加零。这种方法被许多高性能的CNN(卷积神经网络)如AlexNet所采用。

  2. 卷积核大小(Kernel size) ,通常也称为滤波器大小,指的是在输入上滑动窗口的尺寸。选择这个超参数对图像分类任务有巨大影响。例如,小卷积核尺寸能够从输入中提取包含高度局部特征的大量信息。正如您在上面的可视化中所看到的,较小的卷积核尺寸还导致层维度的减小,从而允许更深的架构。相反,大卷积核尺寸提取较少信息,导致层维度更快地减小,通常导致性能更差。大卷积核更适合提取较大的特征。最终,选择适当的卷积核大小将取决于您的任务和数据集,但一般来说,较小的卷积核大小能够提高图像分类任务的性能,因为架构设计者能够将更多层叠加在一起,以学习更复杂的特征!

  3. 步幅(Stride) 表示卷积核每次应移动多少像素。例如,如上所述的卷积层示例中,Tiny VGG在其卷积层中使用步幅1,这意味着对输入的3x3窗口执行点积以产生输出值,然后每次后续操作都向右移动一个像素。步幅对CNN的影响类似于卷积核大小。随着步幅减小,学到的特征更多,因为提取更多数据,这也导致更大的输出层。相反,随着步幅增加,这导致特征提取受限,并且输出层尺寸更小。架构设计者的责任之一是确保在实现CNN时卷积核对输入进行对称滑动。使用上面的超参数可视化来改变各种输入/卷积核维度上的步幅,以理解这个约束!

激活函数(Activation Functions)

ReLU

神经网络在现代技术中非常普遍——因为它们非常准确!如今性能最高的CNN由大量层组成,能够学习更多特征。这些开创性的CNN能够实现如此巨大的准确性,部分原因是它们的非线性特性。ReLU将非线性引入模型中,这是非常必要的。非线性对于产生非线性决策边界是必要的,这样输出就不能被写成输入的线性组合。如果没有非线性激活函数,深度CNN架构将退化为一个等效的卷积层,性能远不如现在。ReLU激活函数被专门用作非线性激活函数,而不是其他非线性函数,比如Sigmoid,因为经验观察表明使用ReLU的CNN训练速度更快。

ReLU 激活函数是一种one-to-one的数学运算:

Figure 3. The ReLU activation function graphed, which disregards all negative data.

该激活函数是对输入张量中的每个值逐元素应用的。例如,如果在值2.24上应用ReLU,则结果将是2.24,因为2.24大于0。您可以通过点击上面网络中的ReLU神经元来观察此激活函数的应用。在上述网络架构中的每个卷积层之后执行修正线性激活函数(ReLU)。注意此层对网络中各个神经元的激活图的影响!

Softmax

Softmax

一个softmax操作起到了关键作用:确保CNN的输出总和为1。因此,softmax操作对于将模型输出缩放为概率非常有用。单击最后一层可以看到网络中的softmax操作。注意,展开后的logits没有在0到1之间进行缩放。为了直观地显示每个logit(未缩放的标量值)的影响,它们使用浅橙色到深橙色的颜色比例进行编码。经过softmax函数处理后,每个类现在对应适当的概率!

也许你会想到标准归一化和softmax之间的区别——毕竟,它们都将logits重新缩放到0到1之间。请记住,反向传播是训练神经网络的关键方面——我们希望正确答案具有最大的“信号”。通过使用softmax,我们实际上是在“近似”argmax,同时获得了可微性。重新缩放不会使最大值比其他logits显著地更高,而softmax会。简而言之,softmax是一个“更柔和”的argmax。

Figure 4. The Softmax Interactive Formula View allows a user to interact with both the color encoded logits and formula to understand how the prediction scores after the flatten layer are normalized to yield classification scores.

池化层(Pooling Layers)

不同的CNN架构中有许多种类型的池化层,但它们都旨在逐渐减少网络的空间范围,从而减少网络的参数和整体计算。上面的Tiny VGG架构中使用的池化类型是最大池化。

最大池化操作在架构设计过程中需要选择核大小和步幅长度。一旦选择了,该操作会在输入上滑动指定步幅的核,而仅选择每个核切片中的最大值,以产生输出的值。可以通过点击上面网络中的池化神经元来查看该过程。

在上述的Tiny VGG架构中,池化层使用2x2的核和步幅为2。这种具体规格的操作导致了75%的激活被丢弃。通过丢弃这么多数值,Tiny VGG更具计算效率,并避免过拟合。

展平层(Flatten Layer)

该层将网络中的三维层转换为一维向量,以适应用于分类的全连接层的输入。例如,一个5x5x2张量将被转换为大小为50的向量。网络的先前卷积层从输入图像中提取特征,但现在是对这些特征进行分类的时候了。我们使用softmax函数对这些特征进行分类,这需要一个一维输入。这就是为什么需要展平层。可以通过单击任何输出类来查看这一层。

资料来源

  • https://poloclub.github.io/cnn-explainer/
  • 视频教学


在Hexo中注入JS脚本


在撰写博客文章时,我们有时需要将JavaScript脚本添加到网页的头部,以便执行特定的功能或效果。

在Hexo中,通过使用injector API,你可以轻松地将自定义的JavaScript文件注入到生成的HTML文件中的 <head> 部分。以下是具体步骤:

创建一个JavaScript文件

首先,在你的Hexo项目中创建一个新的JavaScript文件。例如,你可以在 source/js 目录下创建一个名为 custom.js 的文件。

使用injector API注入JavaScript文件

接下来,在Hexo的配置文件或插件中,使用injector API将JavaScript文件注入到 <head> 部分。以下是一个示例代码:

1
2
3
4
5
6
/* global hexo */
const js = hexo.extend.helper.get('js').bind(hexo);

hexo.extend.injector.register('head_end', () => {
return js('/js/custom.js');
});

上述代码将 custom.js 文件注入到每个生成的HTML文件的 <head> 部分的结束标签之前。

确保JavaScript文件被正确引用

确保你的 custom.js 文件路径正确,并且在Hexo生成的静态文件中可以找到。例如,如果你将 custom.js 文件放在 source/js 目录下,Hexo会自动将其复制到 public/js 目录。

重新生成和部署网站

完成上述配置后,运行以下命令来重新生成并部署你的Hexo网站:

1
2
3
hexo clean
hexo generate
hexo deploy

这样,你的 custom.js 文件就会被注入到每个生成的HTML文件的 <head> 部分。

在Hexo配置文件中使用injector

在Hexo的配置文件中使用injector来注入代码片段是一个非常方便的功能。以下是详细步骤,教你如何在Hexo的配置文件中使用injector:

步骤一:创建自定义代码文件

首先,你需要创建一个你想要注入的代码文件。例如,你可以在 source/js 目录下创建一个名为 custom.js 的文件。

步骤二:在Hexo配置文件中使用injector

在Hexo的主配置文件 _config.yml 中,你可以通过自定义插件或直接在Hexo入口文件中使用injector API来注入代码片段。

方法一:直接在Hexo入口文件中使用

你可以在Hexo项目的根目录下的 index.js 文件中添加以下代码:

1
2
3
4
5
6
/* global hexo */
const js = hexo.extend.helper.get('js').bind(hexo);

hexo.extend.injector.register('head_end', () => {
return js('/js/custom.js');
});

上述代码将 custom.js 文件注入到每个生成的HTML文件的 <head> 部分的结束标签之前。

方法二:通过插件方式使用

你也可以创建一个自定义插件来实现相同的功能。首先,在 scripts 目录下创建一个新的JavaScript文件,例如 injector.js

1
2
3
4
5
6
7
// scripts/injector.js
/* global hexo */
const js = hexo.extend.helper.get('js').bind(hexo);

hexo.extend.injector.register('head_end', () => {
return js('/js/custom.js');
});

然后,在你的 _config.yml 文件中确保包含了 scripts 目录:

1
2
3
# _config.yml
scripts:
- scripts/injector.js

步骤三:重新生成和部署网站

完成上述配置后,运行以下命令来重新生成并部署你的Hexo网站:

1
2
3
hexo clean
hexo generate
hexo deploy

这样,你的 custom.js 文件就会被注入到每个生成的HTML文件的 <head> 部分。

使用injector API中的不同位置

通过这些步骤,你可以灵活地在Hexo的配置文件中使用injector来注入各种代码片段。injector API提供了多种注入位置,包括:

  • head_end:在 <head> 标签之前注入。
  • body_begin:在 <body> 标签之后立即注入。
  • body_end:在 </body> 标签之前注入。

例如,如果你想在 <body> 标签的结束标签之前注入代码,可以这样做:

1
2
3
hexo.extend.injector.register('body_end', () => {
return js('/js/custom.js');
});

通过这些步骤,你可以根据需要灵活地使用injector API来添加JavaScript脚本到你的Hexo网站。


拥有自己的私有大模型

在本教程中,我们将探索如何使用 Ollama 提供的 Modelfile 机制来定制自己的大型语言模型 (LLM)。我们将以 llama3:8b 为例,展示自定义过程。

引言

今天,我将分享如何利用 Modelfile 创建新的模型或调整已有模型,以适应特定的应用场景。这包括内嵌自定义提示、修改上下文长度、温度、随机种子、减少废话程度以及增加或减少输出多样性等(这不是微调,只是调整模型原参数)。

准备工作

在开始定制之前,您需要准备以下几点:

  1. 安装 Ollama

  2. 下载并初始化一个新的模型版本:ollama pull llama3:8b

  3. 确保能成功运行已下载的大语言模型:ollama run llama3:8b

创建 Modelfile

使用 ollama show 命令生成 Modelfile:ollama show llama3:8b --modelfile > myllama3.modelfile

Modelfile 的内容如下所示:

1
2
3
4
5
6
7
8
9
# Modelfile generated by "ollama show"
# To build a new Modelfile based on this, replace FROM with:
# FROM llama3:latest

FROM /Users/yourname/.ollama/models/blobs/sha256-00e1317cbf74d901080d7100f57580ba8dd8de57203072dc6f668324ba545f29
TEMPLATE "{{ if .System }}{{ .System}}{{ end }}"{{ if .Prompt }}{{ .Prompt}}{{ end }}"{{ .Response }}"

PARAMETER stop "reserved_special_token"
LICENSE "META LLAMA 3 COMMUNITY LICENSE AGREEMENT"

例举一些其他模型的modelfile模板:

  • mixtral

    1
    2
    3
    4
    5
    6
    FROM /Users/user/data/ollama-file/models/MiniCPM-Llama3-V-2_5/model/model-Q4_K_M.gguf
    TEMPLATE [INST] {{ if .System }}{{ .System }} {{ end }}{{ .Prompt }} [/INST]
    PARAMETER stop [INST]
    PARAMETER stop [/INST]

    LICENSE """ Apache License Version 2.0, January 2004 """
  • llava

1
2
3
4
5
6
7
8
9
10
11
12

FROM /Users/user/data/ollama-file/models/MiniCPM-Llama3-V-2_5/model/model-8B-F16.gguf
TEMPLATE "<|im_start|>system
{{ .System }}<|im_end|>
<|im_start|>user
{{ .Prompt }}<|im_end|>
<|im_start|>assistant
"
PARAMETER stop <|im_start|>
PARAMETER stop <|im_end|>

LICENSE """ Apache License Version 2.0, January 2004 """
  • other
1
2
3
4
5
6
7
8
9
10
11
12
13
14
FROM /Users/user/.ollama/models/blobs/sha256-eb569aba7d65cf3da1d0369610eb6869f4a53ee369992a804d5810a80e9fa035
TEMPLATE "{{ if .System }}<|start_header_id|>system<|end_header_id|>

{{ .System }}<|eot_id|>{{ end }}{{ if .Prompt }}<|start_header_id|>user<|end_header_id|>

{{ .Prompt }}<|eot_id|>{{ end }}<|start_header_id|>assistant<|end_header_id|>

{{ .Response }}<|eot_id|>"
PARAMETER stop <|start_header_id|>
PARAMETER stop <|end_header_id|>
PARAMETER stop <|eot_id|>
PARAMETER num_ctx 4096
PARAMETER num_keep 4
LICENSE """ Apache License Version 2.0, January 2004 """

添加系统提示

准备好您的系统提示(System Prompt),例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

-----英文 Prompt Start------

## Role and Goal:

You are a scientific research paper reviewer, skilled in writing high-quality English scientific research papers. Your main task is to accurately and academically translate Chinese text into English, maintaining the style consistent with English scientific research papers. Users are instructed to input Chinese text directly, which will automatically initiate the translation process into English.

## Constraints:

Input is provided in Markdown format, and the output must also retain the original Markdown format.
Familiarity with specific terminology translations is essential.

## Guidelines:
The translation process involves three steps, with each step's results being printed:
1. Translate the content directly from Chinese to English, maintaining the original format and not omitting any information.
2. Identify specific issues in the direct translation, such as non-native English expressions, awkward phrasing, and ambiguous or difficult-to-understand parts. Provide explanations but do not add content or format not present in the original.
3. Reinterpret the translation based on the direct translation and identified issues, ensuring the content remains true to the original while being more comprehensible and in line with English scientific research paper conventions.

## Clarification:

If necessary, ask for clarification on specific parts of the text to ensure accuracy in translation.

## Personalization:

Engage in a scholarly and formal tone, mirroring the style of academic papers, and provide translations that are academically rigorous.

## Output format:

Please output strictly in the following format

### Direct Translation
{Placeholder}

***

### Identified Issues
{Placeholder}

***

### Reinterpreted Translation
{Placeholder}

Please translate the following content into English:

-----英文 Prompt End------


创建新模型版本

执行命令:

1
ollama create myllama3 -f myllama3.modelfile

完成后将显示 “success”。

learn2

检查新建的模型版本

运行 ollama ls,查看是否已成功创建。

learn2

运行 ollama run myllama3,查看效果。

如何引入新模型(HF转换成guff文件)
  • Import a model
  • llama.cpp
  • llama定制化(minicpmv)

ModelFile模型文件描述

指令参数
指令 描述
FROM (必填) 定义要使用的基本模型。
PARAMETER 设置 Ollama 如何运行模型的参数。
TEMPLATE 要发送到模型的完整提示模板。
SYSTEM 指定将在模板中设置的系统消息。
ADAPTER 定义要应用于模型的(Q)LoRA 适配器。
LICENSE 指定合法许可证。
MESSAGE 指定消息历史记录。
详细参数设置
参数 描述 值类型 用法示例
mirostat 启用 Mirostat 采样以控制困惑度。(默认值:0、0 = 禁用、1 = 开启) int mirostat=1
mirostat_eta 影响算法对生成文本反馈的响应速度。较低的学习率将导致调整速度较慢,较高的学习率使算法更具响应性。(默认值:0.1) float mirostat_eta=0.2
mirostat_tau 控制输出的一致性和多样性的平衡。较低的值将导致文本更加集中连贯。(默认值:5.0) float mirostat_tau=4.0
num_ctx 设置用于生成下一个标记的上下文窗口大小。(默认值:2048) int num_ctx=4096
num_gqa Transformer 层中 GQA 组数。某些型号需要,例如 llama2:70b 为 8 int num_gqa=2
num_gpu 要发送到 GPU 的层数。在 macOS 上,默认为 1 开启金属支持,0 禁用。 int num_gpu=1
num_thread 设置计算期间使用的线程数。默认情况下,Ollama 将检测到这一点以获得最佳性能。建议将此值设置为系统具有的物理 CPU 核心数(而不是逻辑核心数)。 int num_thread=4
repeat_last_n 设置模型回溯多远以防止重复。(默认值:64,0 = 禁用,-1 = num_ctx) int repeat_last_n=32
repeat_penalty 设置惩罚重复的强度。较高的值(例如,1.5)将更强烈地惩罚重复,较低的值(例如,0.9)将更宽松。(默认值:1.1) float repeat_penalty=1.2
temperature 模型温度。提高温度将使模型答案更有创意。(默认值:0.8)这个值越低准确率越高。 float temperature=0.9
seed 设置用于生成的随机数种子。将其设置为特定数字将使模型为相同的提示生成相同的文本。(默认值:0) int seed=42
stop 设置要使用的停止序列。当遇到这种模式时,LLM 将停止生成文本并返回。可以通过 stop 在模型文件中指定多个单独参数来设置多个停止模式。 string stop="AI assistant:"
tfs_z 无尾采样用于减少输出中不太可能的标记影响。较高的值(例如,2.0)将更多地减少影响,1.0 将禁用此设置。(默认值:1) float tfs_z=1.5
num_predict 生成文本时要预测的最大标记数。(默认值:128,-1 = 无限生成,-2 = 填充上下文) int num_predict=64
top_k 减少产生废话的可能性。较高的值(例如 100)将给出更多样化答案,较低的值(例如 10)将更加保守。(默认值:40) int top_k=30
top_p 与 top-k 一起工作。较高的值(例如,0.95)将导致更多样化文本,较低的值(例如,0.5)将生成更集中和保守文本。(默认值:0.9) float top_p=0.8


ComfyUI新手教程:入门指南

引言

欢迎来到ComfyUI的世界!ComfyUI是一个强大的图形界面工具,专为与深度学习模型协同工作而设计。在这个教程中,我们将引导你逐步了解ComfyUI的基础知识,并帮助你开始构建自己的创意工作流。在我们开始之前,让我们先探讨为什么你应该学习ComfyUI。

为什么选择ComfyUI?

市场上存在着各种类型的产品,它们大致可以分为两类:

  1. 融合型产品:如Midjourney、Stability AI等,它们将模型与产品紧密集成。
  2. 分离型产品:如SD Web UI和ComfyUI,它们允许模型与用户界面分离。

以下两类产品的优缺点对比:

特性 融合型产品 分离型产品
学习成本 低,用户体验优化,提供教程。 高,开源性质,开发者众多,可能缺乏优化和教程。
迁移成本 高,需重新学习产品及模型知识。 低,只需学习模型知识。
自由度 低,封闭系统,功能有限。 高,开源,可自由修改和开发。
费用 高,通常需要付费使用。 中,提供本地版本,可自备GPU,无需额外费用。

选择哪种产品取决于你的需求。如果你只是寻求娱乐,偶尔制作图片或视频,融合型产品可能是更好的选择。但如果你是专业人士,希望利用AI技术创造价值,分离型产品将为你提供更大的灵活性和控制权。

学习ComfyUI的优势

  • 迁移成本低:随着AI行业的快速发展,学会使用ComfyUI等分离型产品,可以让你轻松适应新的模型和技术,无需重新学习整个软件。
  • 高度自由度:ComfyUI允许你调整和优化AI模型,以适应你的工作流程,甚至可以开发新的功能。

SD Web UI与ComfyUI对比

为什么在众多分离型产品中选择ComfyUI?

  • 用户界面:ComfyUI提供了一种独特的图形化工作流搭建方式,通过节点和连线的形式,使得工作流程更加直观和模块化。
    learn2

  • 高度定制化:通过改变节点和连线,你可以轻松构建和调整工作流,以实现不同的功能。
    learn2

开始使用ComfyUI

在本教程中,我们将涵盖以下内容:

  1. 安装和设置:如何正确安装和配置ComfyUI环境。
  2. 基础操作:了解ComfyUI界面,学习如何添加和连接节点。
  3. 构建第一个工作流:通过一个简单的例子,学习如何构建一个基本的工作流。
  4. 进阶技巧:探索如何自定义节点和优化工作流。

准备好了吗?让我们开始你的ComfyUI之旅吧!

开始入门

以下是安装 ComfyUI 的大概步骤:

本地安装方法

命令行安装

  1. 安装 pytorch

    • Windows 用户:使用 Miniconda3 安装 pytorch 的 nightly 版本。
    • Mac 用户:根据芯片类型下载 Miniconda3,然后安装 pytorch 的 nightly 版本。
  2. 下载 ComfyUI

    • 使用 Git 命令 git clone https://github.com/comfyanonymous/ComfyUI
    • 或者使用 GitHub Desktop 客户端下载。
  3. 安装依赖

    • 在 VS Code 中打开项目文件夹,在终端运行 pip install -r requirements.txt
    • 或者直接在 Terminal 中 cd 到项目文件夹,然后运行 pip install -r requirements.txt
  4. 启动服务

    • 在项目文件夹的终端中运行 python main.py

安装包安装

  1. 官方安装包:仅支持 Windows 系统,显卡必须是 Nivida。下载地址:ComfyUI 官方安装包

  2. Jupyter Notebook:要在paperspace、kaggle 或 colab 等服务上运行,可以使用 Jupyter脚本

  3. Mac/Linux:mac和linux环境,请移步官方的安装指南

Q&A

  • 模块下载失败:配置终端代理。
  • pyyaml 错误:运行 pip install pyyaml

完成安装后,打开浏览器输入 http://127.0.0.1:8188/ 即可访问 ComfyUI。默认界面如下图,
learn2

参考

  • ComfyUI 的源码及官方安装教程👉这里

下载 & 导入模型

安装完 ComfyUI 后,你需要下载对应的模型,并将模型导入到 ComfyUI 的 models 目录下。以下是详细步骤:

不同 Stable Diffusion 版本

  • Stable Diffusion v1.5:早期版本,许多 Lora 和 ContrlNet 模型基于它构建。下载地址
  • Stable Diffusion v2.0:重大更新,图像质量和速度提升,采用新的文本编码器 OpenCLIP。release
  • Stable Diffusion XL:最新版本,模型大小更大,生成更高质量的图像。下载地址

模型下载

  1. HuggingFace:搜索并下载模型,推荐下载 safetensors 格式的模型。
  2. CivitAI:搜索并下载模型,提供更多个人训练的模型。

模型导入

  1. 未安装过 SD WebUI:下载模型后,将其放入 ComfyUI 的 models 目录下对应的文件夹。
  2. 已安装 SD WebUI:修改 ComfyUI 中的 extra_model_paths.yaml.example 文件,将其改为 extra_model_paths.yaml,并配置 SD WebUI 的路径。

完成模型导入后,ComfyUI 就可以加载并使用这些模型了。

核心节点介绍

高级节点

Diffusers Loader

Diffusers Loader节点可以用于加载来自diffusers的扩散模型。

输入:model_path(指向diffusers模型的路径。)

输出:MODEL(用于对潜在变量进行降噪的模型)CLIP(用于对文本提示进行编码的CLIP模型。)

VAE(用于将图像编码至潜在空间,并从潜在空间解码图像的VAE模型。)

Load Checkpoin(with config)【加载Checkpoint(带配置)节点】

“加载检查点(带配置)”节点可以根据提供的配置文件加载扩散模型。请注意,常规的加载检查点节点在大部分情况下能够推测出适当的配置。

输入:config_name(配置文件的名称)、ckpt_name(要加载的模型的名称);

输出:MODEL(用于去噪潜在变量的模型)、CLIP(用于编码文本提示的CLIP模型)、VAE(用于将图像编码和解码到潜在空间的VAE模型。)

VAE 解码(tiled)节点

VAE 解码(瓦片式)节点可用于将潜在空间图像解码回像素空间图像,使用提供的 VAE(变分自编码器)。该节点以瓦片的方式解码潜在图像,使其能够解码比常规 VAE 解码节点更大的潜在图像。

信息:当常规 VAE 解码节点由于 VRAM(视频随机存取存储器)不足而失败时,comfy(一种软件)将自动使用瓦片式实现进行重试。

输入参数为待解码的潜在图像和用于解码潜在图像的 VAE。输出结果是解码后的图像。

VAE 编码(tiled)节点

VAE 编码(瓦片式)节点可用于将像素空间图像编码为潜在空间图像,使用提供的 VAE(变分自编码器)。该节点以瓦片的方式编码图像,使其能够编码比常规 VAE 编码节点更大的图像。

信息:当常规 VAE 编码节点由于 VRAM(视频随机存取存储器)不足而失败时,comfy将自动使用瓦片式实现进行重试。

输入参数为待编码的像素空间图像和用于编码像素图像的 VAE。输出结果是编码后的潜在图像。

Conditioning(条件设定节点)

在 ComfyUI 中,Conditioning(条件设定)被用来引导扩散模型生成特定的输出。所有的Conditioning(条件设定)都开始于一个由 CLIP 进行嵌入编码的文本提示,这个过程使用了 Clip Text Encode 节点。这些条件可以通过本段中找到的其他节点进行进一步增强或修改。

例如,使用 Conditioning (Set Area)、Conditioning (Set Mask) 或 GLIGEN Textbox Apply 节点,可以引导过程朝着某种组合进行。

或者,通过 Apply Style Model、Apply ControlNet 或 unCLIP Conditioning 节点等,提供额外的视觉提示。相关节点的完整列表可以在侧边栏中找到。

Apply ControlNet(应用 ControlNet 节点)

Apply ControlNet 节点能够为扩散模型提供更深层次的视觉引导。不同于 unCLIP 嵌入,controlnets 和 T2I 适配器能在任何模型上工作。通过联接多个节点,我们可以使用多个 controlNets 或 T2I 适配器来引导扩散模型。例如,通过提供一个包含边缘检测的图像和一个在边缘检测图像上训练的 controlNet,我们可以向扩散模型提示在最终图像中的边缘应该在哪里。

输入:包括conditioning(一个conditioning)、control_net(一个已经训练过的controlNet或T2IAdaptor,用来使用特定的图像数据来引导扩散模型)、image(用作扩散模型视觉引导的图像)。

输出:CONDITIONING,这是一个包含 control_net 和视觉引导的 Conditioning。

应用样式模型节点(Apply Style Model node)

应用风格模型节点可用于为扩散模型(diffusion model)提供进一步的视觉指导,特别是关于生成图像的风格。该节点接收一个T2I风格适配器(style adaptor)模型和一个CLIP视觉模型(CLIP vision model)的嵌入(embedding),以引导扩散模型朝向CLIP视觉模型嵌入的图像风格发展。

输入:包括条件(conditioning)、T2I风格适配器(style_model)、以及一个由CLIP视觉模型编码的包含期望风格的图像(CLIP_vision_output)。条件是一个特定的条件。T2I风格适配器是一个特定的模型,而CLIP视觉模型的输出是一个包含期望风格的图像。

输出:是一个包含T2I风格适配器和对期望风格的视觉指导的条件(CONDITIONING)。

CLIP 设置最后一层节点 (CLIP Set Last Layer Node)

CLIP 设置最后一层节点 (CLIP Set Last Layer node) [1]用于设置从哪个 CLIP 输出层获取文本嵌入。文本被编码成嵌入的过程是通过 CLIP 模型的多层变换实现的。虽然传统的扩散模型通常根据 CLIP 的最后一层的输出进行条件设定,但有些扩散模型是基于早期层的条件设定的,如果使用最后一层的输出,可能效果不佳。

这个节点的输入 (inputs) 是用于编码文本的 CLIP 模型。输出 (outputs) 则是设置了新的输出层的 CLIP 模型。这样,我们可以根据需要,控制从哪一层获取文本嵌入,以适应不同的扩散模型条件。

CLIP 文本编码 (Prompt) 节点 (CLIP Text Encode (Prompt) Node)

CLIP 文本编码 (Prompt) 节点可以使用 CLIP 模型将文本提示编码成嵌入,这个嵌入可以用来指导扩散模型生成特定的图片。关于 ComfyUI 中所有文本提示相关特性的完整指南,请参阅Text Prompts页面。

这个节点需要输入一个 CLIP 模型和一个需要被编码的文本。CLIP 模型用于将输入的文本转化为嵌入,而输入的文本则是你希望模型理解并生成相关图片的内容。经过这个节点处理后,你将得到一个包含嵌入文本的条件(Conditioning),这个条件用于指导扩散模型生成图片。

CLIP 视觉编码节点 (CLIP Vision Encode Node)

CLIP 视觉编码节点用于使用 CLIP 视觉模型将图片编码成嵌入,这个嵌入可以用来指导 unCLIP 扩散模型,或者作为样式模型的输入。

这个节点的输入包括一个用于编码图片的 CLIP 视觉模型和一个需要被编码的图片。CLIP 视觉模型的任务就是将输入的图片转化为嵌入,而输入的图片则是你希望模型理解并进行处理的图像。经过这个节点处理后,将输出编码后的图片。

平均调节 (Conditioning (Average)) 节点

平均调节节点可以根据在 conditioning_to_strength 中设置的强度因子,将两个文本嵌入值进行插值处理。

输入:参数包括 conditioning_to、conditioning_from 和 conditioning_to_strength。其中 conditioning_to 是在 conditioning_to_strength 为1时的调节文本嵌入值,conditioning_from 则是在 conditioning_to_strength 为0时的调节文本嵌入值。conditioning_to_strength 是用于控制将 conditioning_to 混入 conditioning_from 的混合因子。[2]

输出: CONDITIONING,这是一个新的调节文本嵌入值,它根据 conditioning_to_strength 的设定混合了输入的文本嵌入值。

调节(合并)节点

调节(合并)节点(Conditioning (Combine) node)可以通过平均扩散模型的预测噪声来合并多个调节。注意,这与调节(平均)节点(Conditioning (Average) node)是不同的。在这里,对不同调节的扩散模型输出(即构成调节的所有部分)进行平均,而调节(平均)节点则是在调节内部存储的文本嵌入之间进行插值。

输入包括第一个调节(conditioning_1)和第二个调节(conditioning_2)。输出为一个包含两个输入的新调节(CONDITIONING),稍后将由采样器进行平均。

调节(设置区域)节点

调节(设置区域)节点(Conditioning (Set Area) node)可以用来将调节限制在图像的指定区域内。结合调节(合并)节点(Conditioning (Combine) node),可以增加对最终图像构成的控制。

输入包括将被限制到一个区域的调节(conditioning),区域的宽度(width)、高度(height)、x坐标(x)、y坐标(y),以及在混合多个重叠调节时,要使用的区域的权重(strength)。输出为限制在指定区域的新调节(CONDITIONING)。

调节(设置遮罩)节点

调节(设置遮罩)节点(Conditioning (Set Mask) node)可以用来将调节限制在指定的遮罩内。结合调节(合并)节点(Conditioning (Combine) node),可以增加对最终图像构成的控制。

输入包括将被限制到遮罩的调节(conditioning),约束调节的遮罩(mask),以及在混合多个重叠调节时,要使用的遮罩区域的权重(strength)。还可以设置是否对整个区域进行去噪,或将其限制在遮罩的边界框内(set_cond_area)。输出为限制在指定遮罩内的新调节(CONDITIONING)。

GLIGEN文本框应用节点

GLIGEN文本框应用节点(GLIGEN Textbox Apply node)可以用于为扩散模型提供更进一步的空间指导,引导它在图像的特定区域生成指定的提示部分。虽然文本输入会接受任何文本,但如果输入的是文本提示的一部分对象,GLIGEN的效果最好。

输入包括一个调节(conditioning_to)、一个CLIP模型(clip)、一个GLIGEN模型(gligen_textbox_model)、要关联空间信息的文本(text)、区域的宽度(width)、高度(height)、x坐标(x)和y坐标(y)。输出为包含GLIGEN和空间指导的调节(CONDITIONING)。

unCLIP条件化节点 (unCLIP Conditioning node)

unCLIP条件化节点 (unCLIP Conditioning node) 能够为unCLIP模型提供额外的视觉引导,通过由CLIP视觉模型编码的图像。这个节点可以串联起来,提供多张图像作为引导。

输入参数包括条件化 (conditioning)、由CLIP视觉模型编码的图像 (clip_vision_output)、unCLIP扩散模型应该受到图像多大的引导 (strength) 以及噪声增强 (noise_augmentation)。噪声增强可以用于引导unCLIP扩散模型随机地在原始CLIP视觉嵌入的邻域里移动,提供与编码图像密切相关的生成图像的额外变化。输出则是一种包含了unCLIP模型额外视觉引导的条件化 (CONDITIONING)。

Image(图像)

ComfyUI 提供了各种节点来操作像素图像。这些节点可以用于加载 img2img(图像到图像)工作流程的图像,保存结果,或者例如,为高分辨率工作流程放大图像。

图像反转节点(Invert Image)

图像反转节点可以用来反转图像的颜色。

输入参数为待反转的像素图像。输出结果是反转后的像素图像。

加载图像节点

加载图像节点可用于加载图像。可以通过启动文件对话框或将图像拖放到节点上来上传图像。一旦图像被上传,它们可以在节点内部被选择。

信息:默认情况下,图像将被上传到 ComfyUI 的输入文件夹。

输入参数为待使用的图像名称。输出结果是像素图像和图像的 alpha 通道。

示例:为了执行图像到图像的生成,你需要使用加载图像节点来加载图像。在下面的例子中,一个图像是使用加载图像节点加载的,然后被一个 VAE 编码节点编码到潜在空间,让我们能够执行图像到图像的任务。
learn2

“Pad Image for Outpainting”(为外部绘画填充图像)节点

“Pad Image for Outpainting”(为外部绘画填充图像)节点可用来为外部绘画的图像添加填充,然后将此图像通过”VAE Encode for Inpainting”(为内部绘画编码的变分自动编码器)传递给修复扩散模型。[8]

输入包括图像、左侧、上方、右侧、底部以及羽化。图像是需要被填充的图像。左侧、上方、右侧以及底部分别描述了图像各边需要填充的量。羽化则用于描述原始图像边缘的柔化程度。输出包括被填充的像素图像(IMAGE)和一个用于指示采样器在何处进行外部绘画的遮罩(MASK)。

“Preview Image”(预览图像)节点

“Preview Image”(预览图像)节点可以用来在节点图内预览图像。输入是需要预览的像素图像。这个节点没有输出。

“Save Image”(保存图像)节点

“Save Image”(保存图像)节点可以用来保存图像。如果你只是想在节点图内预览图像,可以使用”Preview Image”(预览图像)节点。当你生成的图像过多,难以跟踪管理时,你可以通过一个带有文件前缀小部件的输出节点传递特殊格式的字符串来帮助组织你的图像。关于如何格式化你的字符串的更多信息,你可以查看Save File Formatting的相关内容。

输入包括需要预览的像素图像,以及一个要放入文件名中的前缀。这个节点没有输出。

图像混合(Image Blend)节点

图像混合(Image Blend)节点用于将两个图像融合在一起。

输入参数包括第一个像素图像(image1)、第二个像素图像(image2)、第二个图像的透明度(blend_factor)及图像混合方式(blend_mode)。输出则是混合后的像素图像(IMAGE)。

图像模糊(Image Blur)节点

图像模糊(Image Blur)节点可以用来对图像应用高斯模糊(Gaussian blur)。

输入(inputs)包括图片(image),这是需要被模糊化的像素图像,高斯半径(blur_radius),以及高斯的西格玛(sigma),西格玛越小,核就越集中在中心像素。输出(outputs)则是模糊化后的像素图像(IMAGE)。

图像量化(Image Quantize)节点

图像量化(Image Quantize)节点可以用来对图像进行量化处理,减少图像中的颜色数量。

输入(inputs)包括图片(image),这是需要被量化的像素图像,颜色(colors),即量化图像中的颜色数量,以及抖动(dither),即是否使用抖动技术使量化图像看起来更平滑。输出(outputs)则是量化后的像素图像(IMAGE)。

图像锐化(Image Sharpen)节点

图像锐化(Image Sharpen)节点可以用来对图像应用拉普拉斯锐化滤波器(Laplacian sharpening filter)。

输入(inputs)包括图片(image),即需要被锐化的像素图像,锐化半径(sharpen_radius),即锐化核的半径,高斯西格玛(sigma),西格玛越小,核就越集中在中心像素,以及锐化强度(alpha),即锐化核的强度。输出(outputs)则是锐化后的像素图像(IMAGE)。

使用模型放大图像(Upscale Image (using Model))节点

使用模型放大图像(Upscale Image (using Model))节点可以用来通过加载放大模型(Load Upscale Model)节点中的模型来放大像素图像。

输入(inputs)包括用于放大的模型(upscale_model)和需要被放大的像素图像(image)。输出(outputs)则是放大后的图像(IMAGE)。

潜在模型(Latent)

像稳定扩散(Stable Diffusion)这样的潜在扩散模型并不在像素空间中操作,而是在潜在空间中进行去噪处理。这些节点提供了使用编码器和解码器在像素空间和潜在空间之间切换的方法,并提供了多种操控潜在图像的方式。

空潜在图像(Empty Latent Image)节点

空潜在图像(Empty Latent Image)节点可以用来创建一组新的空白潜在图像。这些潜在图像可以被例如在text2image工作流中通过采样器节点进行噪声处理和去噪后使用。

输入(inputs)包括潜在图像的像素宽度(width)和像素高度(height),以及潜在图像的数量(batch_size)。输出(outputs)则是空白的潜在图像(LATENT)。

潜在复合(Latent Composite)节点

潜在复合(Latent Composite)节点可以用来将一个潜在图像粘贴到另一个中。

输入(inputs)包括需要被粘贴的潜在图像(samples_to),需要粘贴的潜在图像(samples_from),粘贴潜在图像的x坐标(x)和y坐标(y),以及需要粘贴的潜在图像的羽化程度(feather)。输出(outputs)则是一个包含了粘贴样本(samples_from)的新的潜在复合(LATENT)。

潜在复合遮罩(Latent Composite Masked)节点

潜在复合遮罩(Latent Composite Masked)节点可以用来将一个遮罩的潜在图像粘贴到另一个中。

信息(Info):在ComfyUI中,坐标系统的原点位于左上角。

输入(inputs)包括需要被粘贴的潜在图像(destination),需要粘贴的遮罩潜在图像(source),遮罩(mask),以及粘贴潜在图像的x坐标(x)和y坐标(y)。输出(outputs)则是一个包含了粘贴的源潜在图像(source)的新的潜在复合(LATENT)。

放大潜在图像(Upscale Latent)节点

放大潜在图像(Upscale Latent)节点可以用来调整潜在图像的大小。

警告(Warning):调整潜在图像的大小与调整像素图像的大小并不相同。直接调整潜在图像而不是像素可能会导致更多的图像失真。

输入(inputs)包括需要被放大的潜在图像(samples),用于调整大小的方法(upscale_method),目标像素宽度(Width)和目标像素高度(height),以及是否通过中心裁剪(crop)图片以保持原始潜在图像的长宽比。输出(outputs)则是调整大小后的潜在图像(LATENT)。

VAE解码(VAE Decode)节点

VAE解码(VAE Decode)节点可以用来将潜在空间图像解码回像素空间图像,解码过程使用提供的变分自编码器(VAE)。

输入(inputs)包括需要被解码的潜在图像(samples)以及用于解码潜在图像的变分自编码器(VAE)。输出(outputs)则是解码后的图像(IMAGE)。

VAE编码(VAE Encode)节点

VAE编码(VAE Encode)节点可以用来将像素空间图像编码成潜在空间图像,编码过程使用提供的变分自编码器(VAE)。

输入(inputs)包括需要被编码的像素空间图像(pixels)和用于编码像素图像的变分自编码器(VAE)。输出(outputs)则是编码后的潜在图像(LATENT)。[9]

示例(example):为了在例如图像到图像的任务中使用图像,它们首先需要被编码成潜在空间。在下面的示例中,VAE编码节点被用来将一个像素图像转换成一个潜在图像,这样我们就可以对这个图像进行重新噪声处理和去噪,从而创造出新的图像。

“Latent From Batch”节点

可以用于从一批潜在图像中提取一个切片。当需要在工作流中分离出特定的潜在图像或图像批次时,这将非常有用。

输入参数包括样本(samples,即要提取切片的一批潜在图像),批次索引(batch_index,即要提取的第一张潜在图像的索引),以及长度(length,即要取的潜在图像的数量)。输出结果是LATENT(新的只包含所选切片的潜在图像批次)。

Rebatch Latents节点

Rebatch Latents节点用于拆分或合并一批潜在图像的批次。当结果为多个批次时,该节点会输出一个批次列表,而不是单个批次。这在批次大小超过VRAM(视频随机存取内存)容量时非常有用,因为ComfyUI会按列表中的每个批次执行节点,而不是一次性执行。该节点也可用于将批次列表合并回单个批次。

输入与输出说明:输入”样本”是需要重新分批的潜在图像,”批大小”是新的批次大小。输出”LATENT”是一个潜在图像的列表,其中每个批次的大小不超过”批大小”。

Repeat Latent Batch节点

Repeat Latent Batch节点用于重复一批潜在图像。例如,这可以在图像到图像的工作流中用来创建图像的多个变体。

输入与输出说明:输入”样本”是要重复的潜在图像的批次,”数量”是重复的次数。输出”LATENT”是新的一批潜在图像,将原批次重复了设定的次数。

【Inpaint】”Set Latent Noise Mask”节点

可以用于为用于修复的潜在图像添加遮罩。设定噪声遮罩后,采样器节点只会在遮罩区域进行操作。如果提供了单一遮罩,批次中的所有潜在图像都会使用这个遮罩。

输入参数包括样本(samples,即待修复并添加遮罩的潜在图像),以及遮罩(mask,指示修复位置的遮罩)。输出结果是LATENT(经过遮罩处理的潜在图像)。

【inpaint】”VAE Encode For Inpainting”节点

“VAE Encode For Inpainting”节点可以使用所提供的变分自编码器(VAE)将像素空间的图像编码成潜在空间的图像,并接受一个用于修复的遮罩,向采样器节点指示应去噪的图像部分。通过grow_mask_by可以增加遮罩的区域,为修复过程提供一些额外的填充空间。

这个节点特别设计用于为修复训练的扩散模型,并确保编码前遮罩下的像素被设为灰色(0.5,0.5,0.5)。

输入参数包括像素(pixels,即待编码的像素空间图像),VAE(用于编码像素图像的变分自编码器),遮罩(mask,指示修复位置的遮罩),以及grow_mask_by(用于增加给定遮罩区域的量)。输出结果是LATENT(遮罩处理并编码后的潜在图像)。

【Transform】”Crop Latent”节点

“Crop Latent”节点可以用来将潜在图像裁剪到新的形状。

输入参数包括样本(samples,即待裁剪的潜在图像),宽度(width,裁剪区域的像素宽度),高度(height,裁剪区域的像素高度),以及x和y(区域的像素坐标)。输出结果是LATENT(裁剪后的潜在图像)。

【Transform】”Flip Latent”节点

“Flip Latent”节点可以用来将潜在图像进行水平翻转或垂直翻转。

输入参数包括样本(samples,即待翻转的潜在图像),以及翻转方法(flip_method,即是水平翻转还是垂直翻转)。输出结果是LATENT(翻转后的潜在图像)。

【Transform】”Rotate Latent”节点

“Rotate Latent”节点可以用于将潜在图像以90度的增量顺时针旋转。

输入参数包括样本(samples,即要旋转的潜在图像),以及旋转(rotation,指定顺时针旋转的角度)。输出结果是LATENT(旋转后的潜在图像)。

Loaders,加载器

本段中的加载器可以用来加载各种工作流中使用的模型。所有加载器的完整列表可以在侧边栏中找到。

GLIGEN Loader

“GLIGEN Loader”[11]节点可以用于加载特定的GLIGEN模型。GLIGEN模型用于将空间信息关联到文本提示的部分,引导扩散模型按照GLIGEN指定的组合生成图像。

输入参数是GLIGEN模型的名称(gligen_name)。输出结果是GLIGEN模型(用于将空间信息编码到文本提示部分的模型)。

Hypernetwork Loader

Hypernetwork Loader 节点可用于加载超网络。与 LoRAs 类似,它们用于修改扩散模型,以改变潜在因素的去噪方式。典型的用例包括向模型添加生成某种风格的能力,或更好地生成某些主题或动作。甚至可以将多个超网络链接在一起以进一步修改模型。

提示:超网络强度值可以设置为负值。有时这可能会产生有趣的效果。

输入:

  • model:一个扩散模型。
  • hypernetwork_name:超网络的名称。
  • strength:如何强烈地修改扩散模型。此值可以为负。

输出:

  • MODEL:修改后的扩散模型。
Load CLIP

Load CLIP 节点可用于加载特定的 CLIP 模型。CLIP 模型用于编码指导扩散过程的文本提示。

警告:条件扩散模型是使用特定的 CLIP 模型进行训练的,使用与其训练时不同的模型不太可能产生好的图像。Load Checkpoint 节点会自动加载正确的 CLIP 模型。

输入:

  • clip_name:CLIP 模型的名称。

输出:

  • CLIP:用于编码文本提示的 CLIP 模型。
Load CLIP Vision

Load CLIP Vision 节点可用于加载特定的 CLIP 视觉模型。与 CLIP 模型用于编码文本提示的方式类似,CLIP 视觉模型用于编码图像。

输入:

  • clip_name:CLIP 视觉模型的名称。

输出:

  • CLIP_VISION:用于编码图像提示的 CLIP 视觉模型。
Load Checkpoint

Load Checkpoint 节点可用于加载扩散模型,扩散模型用于去噪潜在因素。此节点还将提供适当的 VAE 和 CLIP 模型。

输入:

  • ckpt_name:模型的名称。

输出:

  • MODEL:用于去噪潜在因素的模型。
  • CLIP:用于编码文本提示的 CLIP 模型。
  • VAE:用于将图像编码和解码到潜在空间的 VAE 模型。
Load ControlNet Model

Load ControlNet Model 节点可用于加载 ControlNet 模型。与 CLIP 模型提供一种给予文本提示以指导扩散模型的方式类似,ControlNet 模型用于为扩散模型提供视觉提示。这个过程与例如给扩散模型一个部分噪声的图像进行修改的方式不同。相反,ControlNet 模型可以用来告诉扩散模型例如最终图像中的边缘应该在哪里,或者主体应该如何摆放。此节点还可用于加载 T2IAdaptors。

输入:

  • control_net_name:ControlNet 模型的名称。

输出:

  • CONTROL_NET:用于为扩散模型提供视觉提示的 ControlNet 或 T2IAdaptor 模型。
Load LoRA

Load LoRA 节点可用于加载 LoRA。LoRAs 用于修改扩散和 CLIP 模型,以改变潜在因素的去噪方式。典型的用例包括向模型添加生成某种风格的能力,或更好地生成某些主题或动作。甚至可以将多个 LoRAs 链接在一起以进一步修改模型。

提示:LoRA 强度值可以设置为负值。有时这可能会产生有趣的效果。

输入:

  • model:一个扩散模型。
  • clip:一个 CLIP 模型。
  • lora_name:LoRA 的名称。
  • strength_model:如何强烈地修改扩散模型。此值可以为负。
  • strength_clip:如何强烈地修改 CLIP 模型。此值可以为负。

输出:

  • MODEL:修改后的扩散模型。
  • CLIP:修改后的 CLIP 模型。
Load Style Model

Load Style Model 节点可用于加载风格模型。风格模型可以用于为扩散模型提供关于去噪潜在因素应该采用的风格的视觉提示。

信息:目前只支持 T2IAdaptor 风格模型。

输入:

  • style_model_name:风格模型的名称。

输出:

  • STYLE_MODEL:用于为扩散模型提供关于所需风格的视觉提示的风格模型。
Load Upscale Model

Load Upscale Model 节点可用于加载特定的放大模型,放大模型用于放大图像。
输入:

  • model_name:放大模型的名称。

输出:

  • UPSCALE_MODEL:用于放大图像的放大模型。
Load VAE

Load VAE 节点可用于加载特定的 VAE 模型。VAE 模型用于将图像编码和解码到潜在空间。尽管 Load Checkpoint 节点提供了一个 VAE 模型和扩散模型,但有时使用特定的 VAE 模型可能会很有用。

输入:

  • vae_name:VAE 的名称。

输出:

  • VAE:用于将图像编码和解码到潜在空间的 VAE 模型。

示例: 有时您可能希望使用与随节点加载的 VAE 不同的 VAE。我们使用不同的 VAE 将图像编码到潜在空间,并解码 Ksampler 的结果。

unCLIP Checkpoint Loader

unCLIP Checkpoint Loader 节点可用于加载专为与 unCLIP 一起工作而制作的扩散模型。unCLIP 扩散模型用于去噪潜在因素,这些潜在因素不仅基于提供的文本提示,还基于提供的图像。此节点还将提供适当的 VAE、CLIP 和 CLIP 视觉模型。

警告:尽管此节点可用于加载所有扩散模型,但并非所有扩散模型都与 unCLIP 兼容。

输入:

  • ckpt_name:模型的名称。

输出:

  • MODEL:用于去噪潜在因素的模型。
  • CLIP:用于编码文本提示的 CLIP 模型。
  • VAE:用于将图像编码和解码到潜在空间的 VAE 模型。
  • CLIP_VISION:用于编码图像提示的 CLIP 视觉模型。

mask遮罩

遮罩为采样器提供了一种方法,告诉它哪些部分应该去噪,哪些部分应该保持原样。这些节点提供了各种方法来创建或加载遮罩并对其进行操作。

convert image to mask

“Convert Image to Mask” 节点可以用来将图像的特定通道转换为遮罩。

输入:

  • image:要转换为遮罩的像素图像。
  • channel:要用作遮罩的通道。

输出:

  • MASK:从图像通道创建的遮罩。
convert mask to image

“Convert Mask to Image” 节点可以用来将遮罩转换为灰度图像。

输入:

  • mask:要转换为图像的遮罩。

输出:

  • IMAGE:从遮罩生成的灰度图像。
crop mask

“Crop Mask” 节点可以用来将遮罩裁剪成新的形状。
信息: ComfyUI 中的坐标系统原点位于左上角。

输入:

  • mask:要裁剪的遮罩。
  • width:区域的像素宽度。
  • height:区域的像素高度。
  • x:区域的 x 坐标(以像素为单位)。
  • y:区域的 y 坐标(以像素为单位)。

输出:

  • MASK:裁剪后的遮罩。

参考:

  • Comflowy - ComfyUI 社区:https://www.comflowy.com/zh-CN
  • comfyUI节点介绍:https://zhuanlan.zhihu.com/p/648278481
  • CLIP模型介绍(主要分Text Encoder和Image Encoder两个模块):https://zhuanlan.zhihu.com/p/666661623


在当今技术领域,大家谈论的时候常常涉及到“大模型”,对于很多新手来说,这个概念可能还比较模糊。为了让大家更好地参与讨论,让我们一起来了解一些关于深度学习和大模型的基础知识。

什么是机器学习?

机器学习简而言之,就是机器通过学习数据,自动找到一个函数。这个函数的作用是,给定输入,输出对应的预测结果。在数学上,这个函数可以表示为 y = f(x),其中 x 是输入,y 是输出。比如,我们可以通过一个函数来预测摄入食物的卡路里,如 卡路里 = 200 * 面包数量。在机器学习领域,这个函数可能是一个包含上千亿参数的巨大函数,只有机器能够处理和理解。

模型

模型(model)就是一个函数,而大模型则是一个巨大的函数。机器学习根据函数输出进行分类,包括回归、分类和生成式学习。

  • 回归(Regression):函数的输出是一个数值,例如通过今天的 PM2.5、温度来预测明天的 PM2.5。
  • 分类(Classification):函数的输出是一个类别,比如判断一封邮件是否为垃圾邮件。
  • 生成式学习(Generative Learning):生成结构化文件,如影像、语音或文句。

什么是深度学习?

深度学习是机器学习的一种,通过深层神经网络学习复杂的表示。以预测YouTube频道观看人数为例,最初的做法是使用线性函数 Y=b+wX。通过定义损失函数,并利用梯度下降方法,寻找最优参数 b 和 w 以使损失最小化。

最原始做法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 定义损失函数
def loss_function(Y, predicted_Y):
return (Y - predicted_Y)**2

# 初始化参数
b = 0
w = 0

# 学习率
learning_rate = 0.01

# 迭代次数
epochs = 1000

# 梯度下降迭代
for epoch in range(epochs):
# 计算梯度
gradient_b = -2 * (Y - (b + w * X))
gradient_w = -2 * X * (Y - (b + w * X))

# 更新参数
b = b - learning_rate * gradient_b
w = w - learning_rate * gradient_w

# 训练后的参数
print("b:", b)
print("w:", w)

但在测试数据上,这种简单线性模型的表现可能不佳。

多看几天的数据

1
2
3
4
5
6
# 使用前7天的数据
X = [day1, day2, day3, day4, day5, day6, day7]

# 其他步骤同上


通过引入更多天数的数据,如前 7 天的数据,我们得到更复杂的模型。逐渐增加参数量,可以提高预测效果,但存在过拟合的风险。

线性模型太简单

线性函数模型(Linear Model 比如 Y=b+wX)因为是直线,非常简单。不能模拟真实情况,真实的情况往往都不是简单线性关系,我们可以通过叠加多个sigmoid函数来达成。

1
2
3
4
5
6
7
8
# 使用多个 sigmoid 函数叠加
def complex_model(X, parameters):
result = 0
for i in range(len(parameters)):
result += parameters[i] * sigmoid(X[i])
return result

# 其他步骤同上

深度学习

深度学习使用多个神经元(sigmoid函数)叠加的方式,构建更复杂的函数模型。神经网络中的每个 sigmoid 函数即为神经元,多层次的叠加构成深度学习模型。深度学习是对神经网络的发展,而不是直接模拟人类大脑。

在深度学习训练时,需要调整一些超参数:

  • Batch size:对训练数据进行分批处理。
  • 学习率:用于梯度下降,影响模型训练速度和精度。
  • 神经元数量:影响函数复杂度,越多越复杂。
  • 隐藏层数:层数越深,函数越复杂。

深度学习的参数数量取决于神经元数量和隐藏层数,而大模型的参数量可能达到千亿级别。

什么是LLM大语言模型?

大语言模型(LLM)是基于海量文本数据训练的深度学习模型。它不仅能生成自然语言文本,还能深入理解文本含义,处理各种自然语言任务。参数量不断提升,使得模型能更细致地捕捉语言微妙之处。

为什么大模型需要大量计算资源?

大模型的计算量可通过 FLOPS 进行估算,通常使用 GPU 进行训练。以 GPT-3 为例,其总算力需求与模型参数量、词数和单词运算量有关。对于训练和推理,计算量需求巨大,需要强大的计算资源,如数千张 GPU 卡。。

跑一下大模型,感受下计算量

通过示例代码,我们可以在本地实践一个大模型的运行,这里以 Microsoft 开源的 Phi-2 Transformer 模型为例。该模型有 27 亿参数,使用 96 张 A100-80G 的显卡训练 14 天完成。代码演示了加载模型和进行推理的过程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 示例代码(以Phi-2 Transformer为例)
import torch
from transformers import GPT2LMHeadModel, GPT2Tokenizer

# 加载预训练模型和分词器
model = GPT2LMHeadModel.from_pretrained("microsoft/philosopher-2.0-large")
tokenizer = GPT2Tokenizer.from_pretrained("microsoft/philosopher-2.0-large")

# 输入文本
input_text = "深度学习是"
input_ids = tokenizer.encode(input_text, return_tensors="pt")

# 生成文本
output = model.generate(input_ids, max_length=50, num_beams=5, no_repeat_ngram_size=2, top_k=50, top_p=0.95, temperature=0.7)

# 解码并打印生成的文本
decoded_output = tokenizer.decode(output[0], skip_special_tokens=True)
print(decoded_output)


参考:

  • 关于深度学习和大模型的基础认知: https://mp.weixin.qq.com/s/Q0746IMKNiX0_5EXAPsNKA
  • 李宏毅深度学习课程:https://www.youtube.com/watch?v=Ye018rCVvOo
  • 梯度下降:https://www.jianshu.com/p/c7e642877b0e
  • phi-2模型:https://huggingface.co/microsoft/phi-2


引言

在当今信息爆炸的时代,随着自然语言处理技术的不断发展,大规模语言模型已经成为了各个领域的核心工具。然而,由于计算成本的限制,这些模型在实际应用中仍存在一些挑战。为了解决这一问题,RAG工程应运而生,它将大规模语言模型与外部知识源相结合,为各种应用场景提供了更高效、准确的解决方案。本文将深入探讨RAG工程的原理、应用场景以及发展前景。

RAG工程的应用场景

RAG工程具有广泛的应用场景,其中最常见的是问答系统。通过将用户问题与知识库进行匹配和检索,RAG工程能够快速找到相关答案,并利用语言模型生成自然、流畅的回复。此外,RAG工程还可以应用于知识推理和文本生成等领域,例如在教育、医疗、金融等行业,为用户提供准确、高效的信息服务。

RAG检索的原理

RAG检索是RAG工程中的核心环节,它通过一系列步骤将用户问题与知识库中的内容进行匹配和筛选。具体来说,RAG检索包括理解问题、检索匹配、筛选排序和生成提示等步骤。首先,需要对用户问题进行语义理解和分析,以确定问题的主题和关键信息。然后,在知识库中进行相关内容的匹配和筛选,确保所选择的内容与问题高度相关。接下来,对检索到的内容进行筛选和排序,以排除不相关或低质量的文本。最后,基于筛选排序后的内容,生成提示给大规模语言模型,指导其生成高质量的回答。

  • 使用余弦相似度算法计算文本相似度

RAG中检索和生成的结合

在RAG工程中,检索和生成是相互关联、相互影响的两个过程。检索过程为生成过程提供了相关的信息和提示,而生成过程则将检索结果转化为最终的回答形式。通过将两者相结合,可以充分发挥大规模语言模型的优势,同时降低计算成本和提高问答系统的准确率。在实际应用中,可以根据问题的类型和复杂程度,灵活地调整检索和生成的过程,以获得最佳的效果。

RAG工程的发展前景

随着自然语言处理技术的不断发展和大规模语言模型的广泛应用,RAG工程在未来具有广阔的发展前景。首先,随着技术的不断进步和应用需求的增加,RAG工程将在更多的领域得到应用。例如,在智能客服、教育、医疗等领域,RAG工程可以帮助提高问答系统的准确率和效率。此外,随着深度学习技术的不断发展,RAG工程中的检索和生成算法将不断优化和完善。例如,可以利用预训练语言模型提高生成的流畅性和自然度,同时利用先进的深度学习技术提高检索的准确性和效率。

结语

RAG工程是一种将大规模语言模型与外部知识源相结合的方法,为各种应用场景提供了更高效、准确的解决方案。随着技术的不断进步和应用需求的增加,RAG工程将在未来的发展中发挥越来越重要的作用。

学习资料

  • RAG论文原文
  • RAG架构指南
    learn
    learn2


引言

在过去的几个季度里,大语言模型(LLM)的平民化运动一直在快速发展,从最初的 Meta 发布 Llama 2 到如今,开源社区以不可阻挡之势适配、进化、落地。LLM已经从昂贵的GPU运行转变为可以在大多数消费级计算机上运行推理的应用,通称为本地大模型。

然而,本地大模型的推理需要相当大的显存,对于16位浮点精度(FP16)的模型,显存需求约为模型参数量的两倍。这使得运行大模型成为对普通家用计算机硬件规格的挑战。为了解决这个问题,模型量化技术应运而生,将权重参数的精度压缩为4位整数精度,大幅减小了显存需求。

在这一背景下,llama.cpp项目通过C/C++重写了推理代码,避免了PyTorch引入的复杂依赖,并提供了更广泛的硬件支持,包括纯CPU推理、Apple Silicon等。然而,llama.cpp的使用仍然对用户有一定的门槛,需要获取模型权重、克隆项目代码、执行模型量化、设置环境变量等。

直到Ollama的出现,一个简明易用的本地大模型运行框架,为用户提供了更便捷的方式在个人电脑上运行大模型。

快速上手

Ollama的安装非常简单,macOS用户只需在官网下载安装包并运行,而Windows用户则可以通过WSL 2以Linux方式用命令进行安装。同时,熟悉Docker的用户也可以直接使用其官方镜像。

1
2
% curl https://ollama.ai/install.sh | sh

安装完成后,通过运行 ollama –version 命令检查版本,确认安装成功后即可通过 ollama pull 命令从在线模型库下载模型。例如,下载中文微调过的Llama2-Chinese 7B模型的4-bit量化版本:

1
% ollama pull llama2-chinese

下载完成后,使用 ollama run 命令即可运行模型并进行推理,支持单条输入或对话模式。

1
2
3
# 单条输入
% ollama run llama2-chinese "天空为什么是蓝色的?"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 对话模式
% ollama run llama2-chinese
>>> /?
Available Commands:
/set Set session variables
/show Show model information
/bye Exit
/?, /help Help for a command

Use """ to begin a multi-line message.

>>> 天空为什么是蓝色的?

这个问题是一个常见的争议。有一些科学家认为天空的蓝色可以被解释为雾和云层中的微小碎片反射出来的光色,而其他人则认为这是由于地球自身温度的影响。目前还没这个问题是一个常见的争议。有一些科学家认为天空的蓝色可以被解释为雾和云层中的微小碎片反射出来的光色,而其他人则认为这是由于地球自身温度的影响。目前还没有一个公认的解释。

套壳玩法

尽管Ollama为用户带来了便利,但命令行形式仍然对一些用户来说不够友好。为此,Ollama提供了一系列周边工具,包括Web界面、桌面应用、终端工具等。其中,Ollama GUI的选择多样,包括Web版本、终端TUI版本(oterm)以及Raycast插件等,以满足用户不同的使用偏好。
传送门

进阶玩法

更换模型

Ollama支持用户自定义系统提示词和调整推理温度等参数。用户可以根据自己的需求选择不同版本的模型,如13B版本,只需在命令中添加对应标签:

1
2
3
4
5
6
7
8
9
10
11
% ollama run llama2-chinese:13b "天空为什么是蓝色的?"

天空是由大气层和太阳光的散射而成的蓝色。

在日出之前,我们看到的天空是紫色或彩虹色,这是因为太阳光从海平面反射回来时,会被大气中的二氧化碳和水分子散射成蓝色、紫色或彩虹色。

而在日出之后,天空变成了灰色,这是由于太阳光从大气中被阻挡,并且不再有足够的反射来给天空增加蓝色。

当我们看到天空时,它的颜色是由于太阳光与大气中的物质相互作用而形成的。这些物质包括水、二氧化碳和其他气体,以及微小的冰片和沙塵。

当我们看到天空变成了晚上时,天空会逐渐变得更加深蓝,这是由于太阳光在大气中传播,同时也因为大气层的结构。

图片支持

除了纯语言大模型,Ollama还从0.1.15版本开始提供了对视觉模型的支持。用户只需在提示中添加本地图片路径即可进行图像文本推理。

1
2
3
4
5
% ollama run llava
>>> What does the text in this image say? /Users/mchiang/Downloads/image.png
Added image '/Users/mchiang/Downloads/image.png'

The text in this image says "The Ollamas."

自定义系统提示词

Ollama允许用户自定义系统提示词,提高模型的个性化。用户可以通过前端工具或直接调用API传入系统提示词选项进行配置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
curl http://localhost:11434/api/chat -d '{
"model": "llama2-chinese:13b",
"messages": [
{
"role": "system",
"content": "以海盗的口吻简单作答。"
},
{
"role": "user",
"content": "天空为什么是蓝色的?"
}
],
"stream": false
}'

更多选项

Ollama的ModelFile提供了更多自定义的空间,包括系统提示词、对话模板、模型推理温度、上下文窗口长度等参数均可自行设置,适合进阶使用者。

在创建前,通过 show --modelfile 命令可以查看现有模型的 ModelFile 内容,作为参考:

1
2
3
4
5
6
7
8
9
10
11
12
% ollama show --modelfile llama2-chinese:13b
# Modelfile generated by "ollama show"
# To build a new Modelfile based on this one, replace the FROM line with:
# FROM llama2-chinese:13b

FROM ~/.ollama/models/blobs/sha256:8359bebea988186aa6a947d55d67941fede5044d02e0ab2078f5cc0dcf357831
TEMPLATE """{{ .System }}
Name: {{ .Prompt }}
Assistant:
"""
PARAMETER stop "Name:"
PARAMETER stop "Assistant:"

以自定义系统提示词并修改推理温度参数为例,应构建如下格式的 ModelFile:

1
2
3
4
FROM llama2-chinese:13b

SYSTEM "以海盗的口吻作答。"
PARAMETER temperature 0.1

然后使用 create 命令进行创建,新的模型会沿用原有模型的权重文件和未作调整的选项参数:

1
ollama create llama2-chinese-pirate -f ~/path/to/ModelFile

从而得到了属于自己的本地模型。

结语

Ollama的出现使得本地大模型的运行变得更加简单快捷。尽管相较于普通应用软件,Ollama的使用体验可能仍有提升空间,但与数月前相比,其进步巨大。称Ollama为AI技术平民化的贡献并不为过,它为更多人以最简单快速的方式在本地运行大模型提供了可能。


RT。

项目需求中实现的一个css3样式写的语音录入效果。

wave

wave2

1
2
3
4
5
6
7
8
9
10
11
<view class="animation start">
<view
class="item"
v-for="(w, idx) in waveStart"
:class="'waveStart-' + w"
:key="idx"
></view>
<view class="item" v-for="(w, idx) in waveList" :class="'wave-' + w" :key="idx"></view>
<view class="item" v-for="(w, idx) in waveEnd" :class="'waveStart-' + w" :key="idx"></view>
</view>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// 时间
$frameTime: 0.5s;
.animation {
flex: 3;
display: flex;
gap: 10rpx;
align-items: center;
&.start {
.item {
animation-iteration-count: infinite;
animation-direction: alternate;
}
}
.item {
width: 8rpx;
background-color: rgba(58, 155, 255, 1);
transform: scale(0.6);
}
.waveStart-1 {
height: 20rpx;
animation: radius-start $frameTime ease;
}
.waveStart-2 {
height: 36rpx;
animation: radius-start $frameTime ease;
}
.waveStart-3 {
height: 52rpx;
animation: radius-start $frameTime ease;
}
.waveStart-4 {
height: 70rpx;
animation: radius-start $frameTime ease;
}

.wave-1 {
height: 8rpx;
animation: radius-animation-1 $frameTime ease;
}
.wave-2 {
height: 20rpx;
animation: radius-animation-2 $frameTime ease;
}
.wave-3 {
height: 36rpx;
animation: radius-animation-3 $frameTime ease;
}
.wave-4 {
height: 52rpx;
animation: radius-animation-4 $frameTime ease;
}
.wave-5 {
height: 70rpx;
animation: radius-animation-5 $frameTime ease;
}
}

@keyframes radius-start {
100% {
height: 8rpx;
}
}

@keyframes radius-animation-1 {
100% {
height: 90rpx;
}
}

@keyframes radius-animation-2 {
80% {
height: 80rpx;
}
100% {
height: 70rpx;
}
}
@keyframes radius-animation-3 {
60% {
height: 80rpx;
}
100% {
height: 52rpx;
}
}
@keyframes radius-animation-4 {
40% {
height: 80rpx;
}
100% {
height: 36rpx;
}
}
@keyframes radius-animation-5 {
20% {
height: 80rpx;
}
100% {
height: 20rpx;
}
}

Vue技术栈&配置

  • eslint + prettier + stylelint + husky
  • 步骤:
    • copy package.json===> devDependencies。完成安装后,陆续补充配置文件👇
    • 文件统一格式: LF

.eslintrc.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

const typescriptEslintRecommended = require('@typescript-eslint/eslint-plugin').configs.recommended;

module.exports = {
root: true,
'env': {
'browser': true,
'es2021': true,
'node': true,
'commonjs': true,
},
'extends': [
'eslint:recommended',
'plugin:vue/vue3-essential',
'plugin:prettier/recommended',
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended"
],
'overrides': [
{
files: ['./**/*.ts'],
parser: '@typescript-eslint/parser',
parserOptions: {
sourceType: 'script',
project: './tsconfig.json',
},
plugins: [ '@typescript-eslint' ],
rules: Object.assign(typescriptEslintRecommended.rules, {
// other customize rules
// @Todo: 暂时设置成warn的rule,后续要设置成error
'@typescript-eslint/no-unused-vars': 'warn',
'@typescript-eslint/no-var-requires': 'warn',
'@typescript-eslint/no-this-alias': ['warn'],
'@typescript-eslint/ban-ts-comment': 'warn',
'@typescript-eslint/no-explicit-any': 'warn'
})
},
{
'env': {
'node': true
},
'files': [
'.eslintrc.{js,cjs}'
],
'parserOptions': {
'sourceType': 'script',
}
}
],
"parser": "vue-eslint-parser",
'parserOptions': {
'ecmaVersion': 'latest',
'sourceType': 'module',
},
'plugins': [
// 'html',
'vue',
"@typescript-eslint"
],
'rules': {
// 'indent': ['error', 'tab'],
// 'linebreak-style': ['error', 'window'],
// 'semi': ['error', 'always'],
'no-underscore-dangle': 'off',
// 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
// 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-unused-vars': 'warn',
'vue/component-name-in-template-casing': ['warn', 'kebab-case'],
'vue/multi-word-component-names': 'off',
'prefer-destructuring': 'off',
'no-plusplus': 'off',
'vue/no-v-text-v-html-on-component': 'warn',
'vue/no-deprecated-slot-attribute': 'warn',
'vue/no-deprecated-v-on-native-modifier': 'warn'
},
globals: {
uni: 'readonly',
plus: 'readonly',
getCurrentPages: 'readonly',
getApp: 'readonly',
this: 'readonly',
wx: 'readonly',
uniCloud: 'readonly'
},
ignorePatterns: ['./pages.json', 'uni_modules', 'unpackage'],
};

.eslintignore

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
uni_modules/
node_modules/
dist/*
unpackage/
uni-*
.*.js
*.log
*.min.js
libs/
vue.config.js

# /node_modules/* in the project root is ignored by default
/node_modules/*

# build artefacts
dist/*
build/*
coverage/*

# data definition files
**/*.d.ts

# 3rd party libs
/src/public/

# custom definition files
/src/types/

apis/

.gitattributes

1
2
3
# Automatically normalize line endings (to LF) for all text-based files.
* text=auto eol=lf

.prettierrc.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

module.exports = {
tabWidth: 4,
useTabs: true,
endOfLine: 'LF',
singleQuote: true,
// 行位是否使用分号,默认为true
semi: false,
trailingComma: 'es5',
// 超过120字符,换行;解决html标签属性换行问题
printWidth: 120,
bracketSpacing: true,
bracketSameLine: false,
eslintIntegration: true,
htmlWhitespaceSensitivity: 'ignore',
}

.prettierignore

1
2
3
4
5
6
7
8
9
10
11
12
# Ignore artifacts:
build
dist
coverage

# Ignore all HTML files:
*.html

.gitignore
.prettierignore
uni_modules

tsconfig.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"strict": true,
"jsx": "preserve",
"moduleResolution": "node",
"esModuleInterop": true,
"sourceMap": true,
"skipLibCheck": true,
"importHelpers": true,
"allowSyntheticDefaultImports": true,
"useDefineForClassFields": true,
"resolveJsonModule": true,
"lib": [
"esnext",
"dom"
],
"types": [
"@dcloudio/types"
]
},
"exclude": [
"node_modules",
"unpackage",
"src/**/*.nvue"
]
}

husky

安装

1
2
3
npx husky install
npx husky add .husky/pre-commit 'npm run lint';

生成的文件内容如下:

1
2
3
4
5
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npm run lint

lint-staged.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
module.exports = {
'*.{js,jsx,ts,tsx,vue}': ['eslint --fix', 'prettier --write'],
'{!(package)*.json,*.code-snippets,.!(browserslist)*rc}': [
'prettier --write--parser json',
],
// for vue web proj
'src/**/*.{js,jsx,ts,tsx,vue}': ['eslint --fix', 'prettier --write'],
// '*.vue': ['prettier --write', 'stylelint --fix --allow-empty-input'],
// '*.{scss,less,styl,css,html}': [
// 'stylelint --fix --allow-empty-input',
// 'prettier --write',
// ],
// 'package.json': ['prettier --write'],
// '*.md': ['prettier --write'],
}

devDependencies

1
2
3
4
5
6
7
8
9
10
11
12
13
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^6.5",
"@typescript-eslint/parser": "^6.5",
"eslint": "^8.47.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-prettier": "^5.0.0",
"eslint-plugin-vue": "^9.17.0",
"husky": "^8.0.3",
"lint-staged": "^14.0.1",
"prettier": "^3.0.2",
"typescript": "^5.2"
}

package.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

{
"scripts": {
"lint": "lint-staged",
"prettier": "prettier --write ./**/*.{js,json,vue}"
},
"husky": {
"hooks": {
"pre-commit": "echo start lint --fix"
}
},
"dependencies": {
"vue-inset-loader": "^1.2.6"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^6.5",
"@typescript-eslint/parser": "^6.5",
"eslint": "^8.47.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-prettier": "^5.0.0",
"eslint-plugin-vue": "^9.17.0",
"husky": "^8.0.3",
"lint-staged": "^14.0.1",
"prettier": "^3.0.2",
"typescript": "^5.2"
}
}

ignore忽略配置

1
2
3
4
5
6
忽略文件
/* eslint-disable */

忽略某一行 & 某一个规则
/* eslint eqeqeq: "off", curly: "error" */

React技术栈&配置

待续