今天了解了一个新的项目,stable-diffusion.java, 这是一个Java 项目,通过底层调用stable-diffusion.cpp, 从而让Java 项目也能AI 画图, 好神奇!
stable-diffusion.java的官网(
https://github.com/javaaiorg/stable-diffusion.java)介绍, stable-diffusion.java 项目是基于stable-diffusion.cpp 的Java项目, 在Java平台上调用Stable Diffusion的 AI 模型,实现从文字到图片转换,也支持从图片到图片的transform, 它支持的Stable Diffusion模型包括v1.4, v1.5, v2.1, 目前支持Mac, Windows和Linux 平台。
stable-diffusion.java的使用也非常简单。
一、添加依赖
首先, 在项目中添加依赖:
org.javaai.stablediffusion
StableDiffusionApi
1.0.4
二、下载Stable Diffusion 模型
然后, 下载Stable Diffusion 模型, 这对于经常使用Stable Diffusion 的人来说是非常简单的:
curl -L -O https://huggingface.co/CompVis/stable-diffusion-v-1-4-original/resolve/main/sd-v1-4.ckpt
# curl -L -O https://huggingface.co/runwayml/stable-diffusion-v1-5/resolve/main/v1-5-pruned-emaonly.safetensors
# curl -L -O https://huggingface.co/stabilityai/stable-diffusion-2-1/resolve/main/v2-1_768-nonema-pruned.safetensors
三、Java 项目中调用Stable Diffusion:加载动态链接库
最后, 就可以在Java 项目中调用Stable Diffusion 了。
调用的时候, 第一步就是要加载动态链接库(dynamic link library):
StableDiffusionLoader.loadShared();
没错的,StableDiffusionApi native 是通过C++来实现的, 还记得最开始介绍的stable-diffusion.cpp吗?
stable-diffusion.cpp
这个是Stable Diffusion 的C++ 版本, 基于ggml,完全通过C++来使用Stable Diffusion。 而stable-diffusion.java 就是stable-diffusion.cpp的Java Binding, 在stable-diffusion.cpp的基础上通过动态链接库,调用stable-diffusion.cpp的方法。
等等, 对于一些AI 小白来说, 什么是GGML?
GGML 是一个用于机器学习的 C 库,允许使用大语言模型在CPU上进行推理。“GG”指的是其创始人 (Georgi Gerganov) 的缩写。
我们一般都或多或少的了解到, 学习AI,尤其是最近的生成式人工智能技术, 非常依赖显卡, 那么这个GGML 又可以做到在CPU 上运行, 甚至不需要显卡, 那这是怎么做到的呢?
答案就在于, 为了做到这一点,GGML使用了量化(quantization)技术,这种量化技术允许 LLM 在消费类硬件上运行,并进行有效的 CPU 推理。
下面这张图片, 非常形象的介绍了什么是量化:
在大语言模型中, 一个典型的LLM,一般包含一个数值矩阵,通常称为权重(weight)。 量化的过程,就是最小化内存消耗,将这些权重转换为更有效的数据类型。
可见, 量化,就是通过数据类型的精度降级,从而减少计算量:
下面这张图解释了LLM中常见的int8、int4等权重长度的单位:
通过采用这种技术,即使是资源最密集的LLM也可以适应在功能较弱的硬件上执行,而不会影响生成响应的速度或准确性。
量化技术根据量化的阶段,有不同的方法,对于在CPU 上进行推理工作而言, GGML 提供了量化的方法。
GGML 支持多种不同的量化策略(例如 4 位、5 位和 8 位量化),每种策略都在效率和性能之间提供不同的权衡。
除了定义低级机器学习原语(如张量类型)之外,GGML 还定义了用于分发大型语言模型 (LLM) 的二进制格式。
四、Java 项目中调用Stable Diffusion
动态库已经封装在相应的jar 里面了, 所以作为Java 程序猿, 只需要执行这个StableDiffusionLoader, 就可以操作Stable Diffusion 了。
如果见到下面的错误, 就要排查动态链接库的加载:
java.lang.UnsatisfiedLinkError: org.javaai.stablediffusion.api.StableDiffusion.newInstance (IZLjava/lang/String; Ljava/lang/String; ZLjava/lang/Boolean; Ljava/lang/String; I)J
如果StableDiffusionAPI 加载成功, 那么就可以创建StableDiffusion 对象:
StableDiffusion sd = new StableDiffusion();
然后加载模型:
sd.loadFromFile(modelPath, null, null, null);
最后, 就可以从文本创建图像了:
StableResult result = sd.txt2img("a lovely cat");
返回值中包含一个Txt2ImgParams 对象和BufferedImage, BufferedImage 就是Stable Diffusion 产生的图像, 而Txt2ImgParams 则包含了调用AI 模型的所有参数, 上面的sd.txt2img("a lovely cat")实际上是一个简化的调用, 下面是参数更多的方法:
StableResult imgs = sd.txt2img("a lovely cat",
null, null, null, null, null, 20,
(long)(Math.random() * Long.MAX_VALUE), null);
最后一步,就是把BufferedImage 写入本地文件:
for (int i = 0; i < imgs.getResultImages().size(); i ++) {
BufferedImage img = imgs.getResultImages().get(i);
ImageIO.write(img, "jpg", new File(outputDir, "sd-java-txt2img-" + i + ".jpg"));
}
就可以得到这种照片啦:
来看一下整体的调用代码:
import org.javaai.stablediffusion.api.SDLogCallback;
import org.javaai.stablediffusion.api.StableDiffusion;
import org.javaai.stablediffusion.api.StableDiffusionLoader;
import org.javaai.stablediffusion.api.Util;
public class Main {
public static void main(String[] args) throws Exception {
StableDiffusionLoader.loadShared();
StableDiffusion sd = new StableDiffusion();
Util.setSDLogCallback(new SDLogCallback() {
@Override
public void onSDLogCallback(int SDLogLevel, String file, int line, String log) {
System.out.println(log);
}
});
boolean loadFromFile = sd.loadFromFile("/Users/u/Desktop/models/sd-v1-4.ckpt", null, null, null);
System.out.println("load:" + loadFromFile);
sd.txt2img("test");
sd.close();
System.out.println("success");
}
}
stable-diffusion.java 还支持从图生成图, 这里不作进一步介绍了, 有兴趣的可以自行去搭建和体验
本文暂时没有评论,来添加一个吧(●'◡'●)