# 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)。效果很好的。