0%


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:裁剪后的遮罩。

参考:


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

什么是机器学习?

机器学习简而言之,就是机器通过学习数据,自动找到一个函数。这个函数的作用是,给定输入,输出对应的预测结果。在数学上,这个函数可以表示为 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)


参考:


引言

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

RAG工程的应用场景

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

RAG检索的原理

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

RAG中检索和生成的结合

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

RAG工程的发展前景

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

结语

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

学习资料


引言

在过去的几个季度里,大语言模型(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技术栈&配置

待续

先引用一句名言:人用制度管,事用流程管

我理解,团队管理分三个维度:

  1. 对上管理
  2. 协作管理
  3. 对下管理

管什么?最主要管的是预期

  1. 老板的预期
  2. 协作方的预期
  3. 组员的预期

以及 我对这三个维度的预期。

先贴个总结
团队管理的几点沉淀
  1. 建立机制,反馈,奖惩,底线(态度),优先级
  2. 团队建设,人才梯度,技术结构,backup
  3. 团队文化,技术氛围、基调
  4. 业务导向,业务结果,规划
  5. 预期管理:对上管理(老板的预期),平行管理(对组员的预期,及组员的预期)
我的预期
  1. 如何教 别人 管理;团队的流程化,职业化?工作流?
  2. 有安全感,归属感,危机感,目标感,非安逸感

关于团队成长

团队的成长离不开组员的成长。一般会基于三个方向来培养组员,帮助成长

  1. backup能力:管理 + 业务
  2. 技术能力:技术栈深度/广度 + 架构设计
  3. 影响力:技术驱动 + 上层思维

从终局思维粗发,如何解读预期管理?

  • 接上面的观点:预期
  • 老板的预期哪里来👉大老板的预期
  • 大老板的预期是什么?当然是公司的营收,业务发展,好早日换车🚗换房🏡换…

所以,包括KPI、OKR什么的,最终目的是帮助老板完成大老板的预期

于是,各业务部门的战术规划,始终都要指向公司的战略目标!

  • 举个例子🌰
  1. 大老板:我们要完成GMV增长50%,利润增长30%
  2. 分析GMV成分:
  • 用户增长
  • 复购、客单
  • 成本控制
  • 新业务拓展
  1. 技术角度要做的事情
  • 技术创新、驱动–>业务效率
  • 组织架构、资源协同
  • 开发效能、稳定性、运维成本
  • 用户体验

那么分到各技术组的目标,就很明确了。

以业务为核心

不管是项目、管理、成长,核心都要基于业务出发,去考虑、规划、组织及架构。

必须要基于业务做的事情,业务导向

  • 组织架构
  • 团队/组员成长
  • 系统设计/架构
  • 基础建设

从业务粗发,如何来做团队管理?

RT。

为什么要总结? 理清思路,整体沉淀。给未来的自己一面镜子,持续地学习、沉淀,构成一个正向成长的飞轮模型✈️。

  1. 在一个电商技术团队中,前端对自己的定位📌
  • 横向支撑
    • 效率
  • 业务导向
    • 沟通
  • 技术驱动
    • 创新

三边关系

  1. 前端团队如何持续成长
  • 搭建团队的成长模型

金字塔成长模型

RT。

大环境不景气,为了生活,必须好好学习了 📚📖

一天一道算法题

1.【链表中倒数第k个节点】两个指针, a=0, b=k,一起向前移动,当k取值=null时,a=n-k。

  • 【 二叉搜索树中第K小的元素】中序遍历,k–
  • 【数组中的第K个最大元素】快速排序,不需要排序,只需要比较。

2.【全排列】递归(DFS), 依次取数组元素,除去当前元素再分别递归取数组元素(两for循环 + 递归)

3.【反转链表】一次循环{prev=null,cur=0, next=temp},当next = null时,结束while循环

4.【二叉树的层序遍历】广度优先BFS:while 同级遍历(队列shift) & 收集下一层节点(push)

5.【螺旋矩阵】巧技:削苹果。削掉最外面一层(shift数组及其余数组pop),翻转整个数组180度([].reverse),再削。

6.【复原IP地址】分割字符串, 递归(dfs), 检查每一段是否合法0~255

7.【岛屿数量】每遇到陆地格子=1, 则DFS搜索,标记已搜索过的格子(标记为2)。

8.【N叉树的层序遍历】BFS广度优先遍历root–>nextRoot[]–>nextRoot[]

9.【翻转二叉树】前、后序DFS深度遍历 or BFS广度优先遍历,不能用中序(会翻转两次)

10.【最长回文子串】https://writings.sh/post/algorithm-longest-palindromic-substring

11.【最长不含重复字符的子字符串】动态规划+ hashMap

12.【二叉树的最近公共祖先】思路1:DFS(二叉遍历)算出路径,然后对比两个路径的分叉点;

  • 思路2:两个值都在左边,则最近root在左边;一左一右,则当前root就是最近公共祖先。

13.【旋转图像】两个for,置换 matrix[j][n - 1- i] = matrix[i][j]

14.【无重复字符的最长子串】滑块->map标识字符位置,max标识当前最大位置

15.【合并两个有序数组】双指针,依次比较放入到一个新数组

16.【求根到叶子节点数字之和】dfs算法,标记已访问过的子节点(左or右)

17.【路径总和】dfs算法,标记已访问过的子节点(左or右)

18.【最大子序和】 单循环下,curSum < 0则舍弃&重新累加,curSum>maxSum && maxSum = curSum

19.【两数之和】建一个map,放入index和value,顺便比对下已放入的是否可以配对

  • 【三数之和】2.双指针法:排序数组 & 选定[a,b,c] = [i,i+1,len-1],target=-num[i]

20.【数组中的第K个最大元素】快排法(选择一个基准p,小于p移到左边,大于p移到右边),从i=0指针移动,如果当前指针 i=k,则return

21.【长度最小的子数组】 滑块->map标识字符位置

22.【字符串相加】转数组&反序reverse,满10进1

23.【二叉树的最大深度】前序遍历
24.【LRU算法】new Map(),map是一个散列队列,set总是到队列最后一个


一些资料

  • 字节算法面试题:github.com/afatcoder/LeetcodeTop/blob/master/bytedance/frontend.md
  • leetcode Top: github.com/afatcoder/LeetcodeTop
  • 看完这篇,你会理解图和树的遍历: https://zhuanlan.zhihu.com/p/98406357
  • 二叉树遍历: github.com/liusaint/ls-blog/issues/25

待续

2023-10-11

  • 记录一些必须要关注的选股指标

    • 量能,交易量,换手率
    • 市场主线,热度,参与度
    • MACD线
    • 近七日成交量趋势
    • 均线走势
    • 【重要】资金流向:结合均线、MACD线及量能、交易量,评估对当前大资金vs散户的占比,判断未来股价走势
      • 大单、中单资金,也有可能是割肉🥩单
      • 小单大部分都是散户单,中单也可能是散户单
    • 筹码分布
  • 重点强调纪律 + 心态


炒股的经验教训沉淀,主要是为了警醒自己Σ(⊙▽⊙”a

  • 设定预期及固定时间点

    • 单支股票的预期上限价格,及计划卖出时间点
    • 单支股票的预期下限价格,及计划卖出时间点
    • 保持个股的资产总额,及持仓占比
  • 重点!!!每只股票,都需要设置自己的预期上限和下限

!切记!

  • 机会每天都有,不必博反弹,不必抄底。
  • 预期 不是 欲望,务必井然有序,执行力要强。

失败案例📚(单支亏损>10w)

  • 同花顺
  • 贝特瑞
  • 易华录(22年新增😔)

基金挑选标准⭐️

  • 基金经理从业6年以上、从业年化收益20%以上、在管规模300亿以下(兴全破例);产品3年夏普比率1.5以上。
    🐔基金推进

待续

为什么要读这本书?

从业十余载,其中从事技术管理工作已有4+年,佛系股龄5+年 👉👉 新韭菜变老韭菜。

期间不乏遇到一些问题,且知识面&认知无法解决。

诸如团队主动性如何调动?奖惩、激励等

又如大盘风向、趋势,及未来规划等

想得越多,盲区越大。

于是,需要慢慢沉淀下来,用时间来消化。

恰巧,看群里推了这本神作,买来看看。

第一章对组织事权的讲解,很多点消化掉,便能用来实践🤔

对事权的理解

  • 事权划分三原则:
    • 规模经济(公共服务的覆盖范围 效益)
    • 信息复杂性(下级的信息优势),
    • 激励相容(有效机制来激励下级完成上级的目标)

  • 关于 房住不炒 的理解
    • RT。 首先要清楚,房价为什么会这么高?它是地区经济发展某一阶段的必然产物.
      1. 土地在城市化快速推进的过程中起到的杠杆作用
      • 地方政府将土地作为资本注入融资平台(城投、产业引导基金等LP),撬动为城市建设服务的资金杠杆
      • “注入土地-土地抵押-城市建设-土地升值-土地出让-还债”的模式成为地方政府通过融资平台举债融资、基建投资的最基本运营模式。导致政府显性、隐形 债务巨大。
      1. 产业基建快速发展,大量人口涌入;但忽略民生建设,居民收入水平提升有限
      2. 不动产持续增值,吸引大量投资客入场;不动产货币化、以土地为信用锚的现象
    • 所以,为什么我国前些年GDP一直在高速增长。驱动GDP增长的主要因素(三家马车)
      • 消费->内销、居民可支配收入->旅游为GDP贡献巨大,占10%+
      • 外贸->出口、跨境->2021年上半年外贸为主要的GDP贡献来源,占30%+
      • 房地产->城市化快速推进的产物,完全(直接&间接)贡献约17%的GDP
        • 说明:欧美房地产的GDP贡献,包括租金和税收,二手房交易及贷款的贡献占比很小。
    • 从另一个角度看,我们的房地产产业结构属于粗放型,需要一系列改革,实现集约型增长。
      • 服务于民生,有利于内循环
      • 降杠杆,解耦地方债务;符合城市多元化、都市圈发展方向
    • 那么,如何改善产业结构👉房住不炒。我理解,这是未来我国五到十年的政策核心,使得GDP结构朝着可持续的集约型经济增长
      1. 改善居民可支配收入,民生服务
      2. 改善外贸的工厂模式,产能过剩问题
      3. 优化房地产产业结构
    • 那么,目前可预见的,如何改善房地产产业结构?我理解
      1. 房市从卖方市场全面转向买方市场
      2. 卖方有两个方向
      • 投向租赁市场
      • 套现离场
      • 交税,贡献GDP(目前,除了房屋买卖,持有不动产是不交税的,不贡献GDP)
    • 所以,房产税势在必行,且肯定是针对卖方。
    • 那么房地产以后就不会继续增值了么?要看具体区域
      • 二三线城市,配套不成熟,or 没有配套升级规划的
      • 一线都市圈核心城市,且是核心区域的房市,理论上是有升值空间的。
    • 但整体上,房价不会涨,至少涨不过居民收入,通货膨胀,弱化投资理财属性。
      • 也不会跌,至少不会大跌,出现恐慌性抛盘,因为房价与民生及地方经济的稳定息息相关
    • 关于地域间的发展不平衡
      • 一般,房价涨幅应该与当地人均GDP相匹配。比如加州的人口占米国约12%,相应的GDP也占了12%
      • 反观我们,内地人口大省如河南,人口超东部沿海省市,但GDP远低于东部,导致人均GDP偏低
      • 所以,规划发展都市圈及户籍改革,有助于改善地域间发展不平衡的现状,让低收入者进入高收入城市,发展第三产业;且第三产业的发展,也有利于招商引资&人才引进,发展优化土地配置,提高利用率,使得房价与人均GDP相匹配

待续