---
# System prepended metadata

title: Novel AI 部署与开发文档

---

# Novel AI 部署与开发文档

本文旨在描述如何从头部署一个社区版 Novel AI 原生的前后端（即 NAIFU），并进行后续定制开发。请按需从目录跳转到对应章节。

## 部署前后端

> **参考：[Google Colab 文档](https://colab.research.google.com/drive/1_Ma71L6uGbtt6UQyA3FjqW2lcZ5Bjck-)**

本方案实测可在任何 Ubuntu 版云计算机（华为云ECS、阿里云ECS）迅速安装完成 NAIFU，非常好用。

### 软硬件要求

- 系统：Linux。理论上支持 Windows，但需要手动执行安装脚本。本文先不写了。
- 显卡：16GB 显存及以上。因为渲染图片会占用 9G 显存，所以理论上 8G 显存的显卡（如 3070）就不太行。

### 安装方法

```bash=
#!/bin/bash
sudo apt-get update -y
sudo apt-get upgrade -y

# install python
sudo apt-get install python3 python-is-python3 python3-virtualenv

# install naifu
sudo apt install -y -qq aria2 python3 python3-pip
aria2c --summary-interval=5 -x 3 --allow-overwrite=true -Z https://pub-2fdef7a2969f43289c42ac5ae3412fd4.r2.dev/naifu.tar   
tar xf naifu.tar && rm naifu.tar
cd naifu
bash ./setup.sh
sed -i 's/$PYTHON -m uvicorn --host 0.0.0.0 --port=6969 main:app & bore local 6969 --to bore.pub/$PYTHON -m uvicorn --host 0.0.0.0 --port=6969 main:app/g' run.sh

# install caddy
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt-get update -y
sudo apt install -y caddy

# add systemd service 
cat << EOF | sudo tee  << EOF > /etc/systemd/system/naifu.service
[Unit]
Description=Naifu Web Service

[Service]
WorkingDirectory=/root/naifu
ExecStart=/root/naifu/run.sh

Restart=always
RestartSec=10

StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=autodeploy

[Install]
WantedBy=multi-user.target
EOF
```

建议直接跑这个脚本。它轮流做了几件事：

1. 在当前目录下，下载解压 naifu 项目（约9gb）。并自动安装创建 python 环境和安装依赖。
2. 安装 caddy 以进行反向代理，如果不需要 Web 服务器可删掉 12~17 行的代码。
3. 创建一个 systemd service 来持续 + 自动重启 naifu 服务。

如果不需要，可以删掉相关部分。

### 启动 naifu

直接启动

```bash
$ bash run.sh
```

等待提示完成，然后访问 http://127.0.0.1:6969/ 应该能看到页面并正常使用，说明部署完成。

### 持久化运行

配置一下 Caddy, 修改 `/ect/caddy/Caddyfile` 文件为：

```
<your-domain> {
  reverse_proxy 127.0.0.1:6969
}
```

然后，重启 caddy 并持续化运行 naifu。

```bash
sudo systemctl enable --now naifu

# 等上面那行启动完成，建议2分钟后再执行下面
sudo systemctl restart caddy
```

可以用 `systemctl status naifu` 查看 naifu 的状态。


## 部署 DeepDanbooru

### 安装

```bash
cd ~
git clone https://github.com/KichangKim/DeepDanbooru.git
mkdir DeepDanbooru/model
cd DeepDanbooru/model
wget https://github.com/KichangKim/DeepDanbooru/releases/download/v3-20211112-sgd-e28/deepdanbooru-v3-20211112-sgd-e28.zip

apt install unzip -y
unzip deepdanbooru-v3-20211112-sgd-e28.zip
rm deepdanbooru-v3-20211112-sgd-e28.zip
```

### 修改文件

`deepdanbooru/commands/evaluate.py` 文件需要注释掉最下面的一个 for 循环的一些代码。改为：

```python=98
    for image_path in target_image_paths:
        # print(f"Tags of {image_path}:") #yup!
        # if save_txt: tag_list = []
        # for tag, score in evaluate_image(image_path, model, tags, threshold):
        #     print(f"({score:05.3f}) {tag}")
        #     if save_txt: tag_list.append(tag)
        # if save_txt:
        #     txt_file_path = str(os.path.splitext(image_path)[0]) + ".txt"
        #     save_txt_file(txt_file_path, tag_list)
        print(json.dumps([tag for tag, score in evaluate_image(image_path, model, tags, threshold)]))
```


***然后，还需要在开头加上 `import json`***

可以对照一下下图：

![image](https://user-images.githubusercontent.com/68253563/202115990-afd0ee85-4038-400f-a4ec-da540f3714e8.png)

最后安装：

```bash!
ubuntu@ip-172-31-22-171:~/DeepDanbooru$ pip install .
```

## 部署 Deppdanbooru-backend

部署我自己写的 [deepdanbooru-backend](https://git.starblazer.cn/gululu/deepdanbooru-backend)，步骤：

1. 装 node 依赖
2. 配置 `.env` 文件如下，按需更改文件路径：

```bash
PORT=3002

PROJECT_PATH=/root/deepdanbooru-backend
DEEPDANBOORU_PROJECT_PATH=/root/DeepDanbooru/model
```

3. 运行

## 对外映射 API

- 反向代理 **`/generate` 到 `NAIFU`** （默认 `127.0.0.1:6969`）
- 反向代理 **`/tag` 到 `deepdanbooru-backend`** （默认 `127.0.0.1:3002`，如上 `.env` 所示）




## NAIFU 二次开发（对部署不重要）

如果要自己实现一个前端或者聊天平台机器人，建议直接调用这个版本的后端接口。该版本后端接口为 REST 接口，和请求标准的后端服务一样就行。

### 例子

👇 下面是一个 TypeScript 的例子：

```typescript=
import axios from 'axios';

async function text2image(prompt: string): Promise<string> {
  const { data: response } = axios.post(
    '<your-server-domain>/generate',
    {
      prompt: `masterpiece, best quality, ${prompt}`,
      width: 512,
      height: 768,
      scale: 12,
      sampler: 'ddim',
      steps: 40,
      seed: Math.floor(Math.random() * 2 ** 32),
      n_samples: 2,
      ucPreset: 3,
      uc:
        'nsfw, lowres, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped,' +
        ' worst quality, low quality, normal quality, jpeg artifacts, signature, watermark, username, blurry',
    },
    {
      headers: {
        'Content-Type': 'application/json',
      },
    },
  );
  const base64 = response.output?.[0] || '';
  return 'data:image/png;base64,' + base64;
}
```

请替换上面代码的 `your-server-domain` 为你的服务器地址。

这个函数如果正常执行，会返回一张基于 `prompt` 的图片地址。地址以 base64 编码并加上了 `data:image/png;` 的 URL 前缀，可以直接被 HTML 渲染。

比如说：

```javascript=
// make an API request
const url = await text2image('a cat');

// convert this base64 url to blob to open it in your webbrowser
const blob = await (await fetch(url)).blob();

// log the url
console.log(window.URL.createObjectURL(blob));
// and open the url in a new tab
window.open(window.URL.createObjectURL(blob), '__blank');
```

### 接口分析

*服从度* 等用词，见[**术语解释文档**](https://bot.novelai.dev/usage.html#%E9%AB%98%E7%BA%A7%E5%8A%9F%E8%83%BD)。

```javascript
{
  prompt: 关键词,
  width: 图片宽度,
  height: 图片高度,
  scale: 服从度,
  sampler: 采样器,
  steps: 步骤,
  n_samples: 生成图片数量,
  seed: 可不传，种子，建议随机生成,
  image: 可不传，基于这张图片来生成一个图片（图片生成模版），格式为图片的 base64 字符串,
  ucPreset: NovelAI 默认提供过滤图片的规则列表，按顺序比如传0是默认，传3是第4个，在0的基础上多 ban 了 nsfw,
  uc: ban掉的词的列表，用逗号分隔，俗称反咒,
}
```

像上面我的例子那样，拼一个这样的 JSON object 用 POST 请求发到你的后端的 `/generate` 接口。你会得到

```json=
{
  "output": [
    "图片1（格式：base64 文本）",
  ]
}
```

如果还有图片2，那就是 `response.output[1]` 以此类推。

另外关于支持中文关键词，就在请求接口之前机翻关键词（可网上查询如何对接翻译 API）。效果很好的。

