类型:安装指南 + 使用手册 + 实战排障备忘
整理日期:2026-10-18
验证环境:Ubuntu Server、Docker Compose、SillyTavern Docker 镜像、Node.js v24.21.0、EasyTier、sub2api、mihomo 代理
适用对象:希望用 SillyTavern 接入 OpenAI 兼容接口,长期写中文小说、角色扮演,并启用向量检索记忆的用户。
0. 先说结论
这套方案不需要额外部署 ChromaDB。SillyTavern 自带 Vector Storage 扩展,选择 Local (Transformers) 时可以在服务端运行 Embedding 模型,将聊天记录向量化后按语义检索。写长篇小说时,推荐 世界书 + 作者注释 + Summarize + 向量检索 结合使用。
本次实际排障中,“全部向量化”最初提示 23 条消息失败,服务器日志报 TypeError: fetch failed、ETIMEDOUT;最终通过正确填写容器代理地址与端口、启用 Node.js 环境代理、换用多语言 Embedding 模型,再次向量化成功。
1. 本次环境与架构
电脑/手机浏览器
|
| http://<Ubuntu主机IP>:18088(仅可信网络)
v
SillyTavern(Docker)
|-- 小说生成 -> sub2api(OpenAI 兼容接口)
| http://10.144.144.1:18080/v1
|
|-- 聊天向量化 -> Local (Transformers) -> 本地模型
| 首次从 Hugging Face 下载
| 经 EasyTier -> HTTP代理 10.144.144.1:17890
|
|-- 角色卡 / 世界书 / 作者注释 / Summarize
v
宿主机持久化目录 ~/ai-workstation/data/sillytavern/本次实测参数
特别注意:这些 IP、端口和路径对应本文作者的机器,不是 SillyTavern 的默认值。迁移部署时必须根据自己的网络修改。sub2api 和代理属于现有外部服务,本文不负责从零安装它们。
2. 安装 Docker 和 Compose
如果 Ubuntu 已经能正常执行 docker ps 与 docker compose version,可以直接跳到第 3 节。以下用于全新 Ubuntu 主机,参考 Docker 官方 Ubuntu 安装说明。
# 安装基础依赖
sudo apt update
sudo apt install -y ca-certificates curl
# 导入 Docker 官方仓库签名
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
-o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# 配置官方 APT 软件源
sudo tee /etc/apt/sources.list.d/docker.sources >/dev/null <<EOF_DOCKER
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF_DOCKER
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io \
docker-buildx-plugin docker-compose-plugin
sudo systemctl enable --now docker
# 验证
docker --version
docker compose version
sudo docker run --rm hello-world如果当前用户无 Docker 权限,可以暂时在命令前加 sudo。也可以把当前用户加入 docker 组,但docker 组基本等同于拥有宿主机 root 级权限,不要随意授权不可信账户。
3. 准备持久化目录
本文将 Compose 文件和数据分开存放,便于备份和迁移。
mkdir -p ~/docker_compose/sillytavern
mkdir -p ~/ai-workstation/data/sillytavern/{config,data,plugins,extensions}
cd ~/docker_compose/sillytavern目录作用:
不能只备份 Compose 文件,因为真正的聊天和角色信息保存在持久化的数据目录中。
4. 编写 docker-compose.yml
下面是本次已成功运行的网络参数整理版,包含代理设置。若没有 mihomo/EasyTier,应删掉 HTTP_PROXY、HTTPS_PROXY、NODE_USE_ENV_PROXY,并根据实际情况调整 NO_PROXY。
services:
sillytavern:
image: ghcr.io/sillytavern/sillytavern:latest
container_name: sillytavern
hostname: sillytavern
restart: unless-stopped
ports:
- "18088:8000"
environment:
- NODE_ENV=production
- FORCE_COLOR=1
- HTTP_PROXY=http://10.144.144.1:17890
- HTTPS_PROXY=http://10.144.144.1:17890
- NODE_USE_ENV_PROXY=1
- NO_PROXY=localhost,127.0.0.1,10.144.144.1
extra_hosts:
- "host.docker.internal:host-gateway"
volumes:
- ~/ai-workstation/data/sillytavern/config:/home/node/app/config
- ~/ai-workstation/data/sillytavern/data:/home/node/app/data
- ~/ai-workstation/data/sillytavern/plugins:/home/node/app/plugins
- ~/ai-workstation/data/sillytavern/extensions:/home/node/app/public/scripts/extensions/third-party关于代理的三个细节:
这里采用 Compose 列表格式
- KEY=VALUE,不可混写成- KEY: VALUE。列表格式中应写
- NODE_USE_ENV_PROXY=1,不要写- NODE_USE_ENV_PROXY="1",否则引号可能成为变量值的一部分。17890是该代理服务暴露在远端宿主机的端口;7890是其容器内部端口。跨机器经 EasyTier 访问时使用前者。
如果只允许 SSH 隧道或本机访问,可将端口映射改为 127.0.0.1:18088:8000;需要局域网访问时再明确控制防火墙和访问认证。不要将未经保护的酒馆直接暴露公网。
启动容器
# 在 docker-compose.yml 所在目录执行
docker compose config -q # YAML 校验,无输出一般即通过
docker compose pull
docker compose up -d
docker compose ps
docker logs --tail 80 sillytavern第一次启动会拉取镜像、生成配置,耗时取决于网络。latest 标签会随版本变化;生产环境需要更可控时可固定为经过验证的版本标签。
5. 首次访问、监听与安全配置
浏览器访问:
http://<Ubuntu主机的局域网IP>:18088如果打不开,先看日志、端口和本机访问:
docker compose ps
docker logs --tail 100 sillytavern
curl -I http://127.0.0.1:18088SillyTavern 的 config.yaml 位于本文挂载的:
~/ai-workstation/data/sillytavern/config/config.yaml如果需要从其他设备连接,通常需要将已存在的 listen 配置设为 true,同时正确配置白名单和/或认证。不同镜像版本的默认行为可能不同,以当前配置和启动日志为准。
示例(将示例网段换成真正使用的内网):
listen: true
whitelistMode: true
whitelist:
- 127.0.0.1
- ::1
- 192.168.31.0/24不要直接覆盖整个 config.yaml;在已生成的文件中编辑已有字段,并保留原有其他设置。Docker 网络、反向代理或 NAT 情况下,酒馆看到的客户端 IP 可能不同,应根据日志中的拒绝来源调整规则。不要为了方便直接关闭全部安全检查。
安全建议:使用私有网络或可信反向代理;为远程访问配置有效认证;代理、SillyTavern、sub2api 的端口不要无防护暴露公网。官方不建议直接公网端口转发酒馆。
6. 接入 sub2api / Gemini
这一步让酒馆负责前端、角色和提示词,让现有的 sub2api 负责模型 API 转发。
6.1 先测 API 是否通
从 Ubuntu 宿主机执行(把密钥替换成自己的,不要把真实密钥贴进博客):
curl -i http://10.144.144.1:18080/v1/models未带密钥返回 401 Unauthorized,可能表示接口网络已经接通,但鉴权失败,并不一定是地址错误。
带密钥验证时推荐交互输入,减少密钥暴露在 shell 历史记录里的机会:
read -rsp 'sub2api key: ' SUB2API_KEY; echo
curl -sS -H "Authorization: Bearer ${SUB2API_KEY}" \
http://10.144.144.1:18080/v1/models
unset SUB2API_KEY确认返回的模型列表中包含你有权限使用的实际模型 ID。模型名称会随网关配置变化,以 /v1/models 返回值为准。
6.2 酒馆界面配置
进入顶部 API Connections(API 连接,插头图标):
API 类型:Chat Completion / 聊天补全。
来源:Custom (OpenAI-compatible) / 自定义(兼容 OpenAI)。
API 地址:
http://10.144.144.1:18080/v1。API Key:填入 sub2api 的密钥。
模型:从
/v1/models返回的列表选择,例如本次使用过的gemini-3.8-flash-high(属于网关中的模型标识,能否使用以实际返回为准)。执行连接或发送测试消息,确认获得模型回复。
地址填写 /v1,不要多填 /chat/completions。如果模型能列出但回复失败,检查是否拥有调用权限、模型标识是否正确、网关服务是否有上游错误。
7. 将 SillyTavern 用作小说创作工具
本次使用场景是万界旅行长篇小说:小伊为第三人称主角,阿莫尔和纳西妲按故事时间线逐渐加入;用户在故事外以观众/导演身份观看。
7.1 角色卡(Character Card)
角色卡负责规定 GM/小说作者是谁、世界基础、人物控制权、叙述方式。如果使用“观众模式”,角色卡中不要保留“禁止控制用户角色”“每轮等待玩家选择”等互动模式规则。
核心描述可以这样写:
你是长篇中文小说《界枢》的主持人和作者,不是第四名队员。
采用第三人称有限视角,以小伊为主要视角人物。
小伊、阿莫尔、纳西妲及其他角色都由作者自主描写。
人物必须遵循已建立的人设、能力限制、世界规则与剧情事实。
不输出选项菜单,不反复询问用户下一步做什么。
从小伊的第001次新人任务开始,不得把未来已规划的事件提前当作既定历史。
小说优先通过人物行动、对白和实际后果推进,减少模板化旁白。7.2 世界书(World Info)
世界书用于长期稳定的设定:界律规则、界枢城、角色核心档案、人物关系、不同世界的知识。
蓝色常驻别放过多超长细节,否则上下文浪费严重。世界书的作用是在适当时提供设定,不是自动写入准确的剧情存档。
7.3 提示词管理器与作者注释
在 AI Response Configuration / 提示词管理器 中,为小说另存独立的预设,明确第三人称有限视角与自主推进要求。检查 Main Prompt 和 Post-History Instructions,清理与“观众模式”冲突的旧提示词。
Author's Note(作者注释) 适合记录当前任务编号、场景、伤势和临时风格重点。可先设为聊天内插入、深度 1、频率 1。注意:聊天专属作者注释不会自动传到新聊天,需要确认并重新设置。
示例:
【当前进度】第001次新人任务;小伊尚未与阿莫尔、纳西妲正式组队。
【叙述】第三人称有限视角,以小伊为主角,自主续写自然中文小说。
【限制】人物能力不能无依据增强;保留时间、位置、物资及行为后果的连续性。7.4 如何开始、如何继续
新建聊天,检查没有携带旧任务的作者注释、历史摘要或“第004次组队”世界书条目;先从第001次新人试炼开场。首次可发送:
【导演指令】从小伊的第一次任务开始,使用第三人称有限视角写正式小说正文。
由你自主安排人物行动与剧情,不用询问我的选择,不生成选项菜单。
不要急于让阿莫尔和纳西妲登场,重视人物行动、空间关系、实际困难与后果。以后发送“继续”即可继续生成;它不会在后台无人触发地一直写。发现设定冲突时,用导演指令纠正,然后根据情况修改世界书或作者注释。
8. 长篇小说的四层记忆
8.1 Summarize(总结)
在顶部 Extensions / 扩展 → Summarize(总结) 中开启,来源选择 Main API 即可复用当前模型。可以先手动试一次,再决定是否每约 15~30 条消息更新一次(实际以篇幅和上下文消耗调整)。
建议摘要重点保留:时间地点、任务条件、角色状态、装备和金钱变化、重要对话、承诺、关系变化、尚未解决的问题。
摘要是模型写的,可能遗漏或编造内容,需要定期人工检查;不建议将其视为绝对可靠的数据库。
8.2 Vector Storage(向量存储)
SillyTavern 自带向量扩展。其本地向量存储使用 Vectra,并保存在酒馆用户数据目录中的 vectors 文件夹。它不等同于已有 ChromaDB,不能直接填 ChromaDB 的 IP 就完成对接。
开启路径:顶部 Extensions / 扩展 → Vector Storage / 向量存储。
本次使用的初始配置:
注入模板:
【与当前剧情相关的历史片段】
{{text}}{{text}} 是占位符,不能删。这些值只是本次运行的起始参数,不是通用最优值。
8.3 修改中文 Embedding 模型
SillyTavern 默认的本地模型是 Cohee/jina-embeddings-v2-base-en,更偏向英文;中文小说可先换成支持多语言的:
Xenova/paraphrase-multilingual-MiniLM-L12-v2打开挂载目录下的 config.yaml,修改已有 extensions.models.embedding:
extensions:
models:
autoDownload: true
embedding: Xenova/paraphrase-multilingual-MiniLM-L12-v2这段仅表示配置的层级,不要覆盖原配置文件的其他 extensions 字段,也不要重复添加同名节点。修改后重启容器:
docker restart sillytavern首次使用 Local (Transformers) 时会从 Hugging Face 下载模型配置、Tokenizer 和 ONNX 权重。模型能否成功下载依赖服务器实际网络;默认主要由 Node.js 本地运行,通常不需要 RTX 3090 显存。
换了 Embedding 模型或向量来源后,旧索引需要重新生成,不同模型的向量不应混用。
8.4 首次生成和验证
在“聊天消息向量化”区域点击 Vectorize All / 全部向量化,完成后点击 View Stats / 查看统计数据,确认当前聊天向量数量增加。聊天向量区域的 Purge Vectors 只清理当前聊天对应索引;不要误点文件向量化区域的同名按钮。
成功生成向量不等于一定能准确找回故事伏笔;后续仍需要通过实际剧情与提示词检查验证检索质量。
9. 本次排障全记录:23 条消息被跳过
问题一:点“全部向量化”后失败
界面提示约 23 条消息未能向量化。查看容器日志:
docker logs --since 10m sillytavern 2>&1 | \
grep -Ei 'error|vector|embed|transform|onnx|fetch|timeout' | tail -n 80最初的关键输出:
Initializing transformers.js pipeline for task feature-extraction
with model Cohee/jina-embeddings-v2-base-en
[TypeError: fetch failed]
AggregateError [ETIMEDOUT]
connect ETIMEDOUT 199.59.149.206:443
connect ENETUNREACH <某IPv6地址>:443含义:酒馆尝试初始化本地 Embedding 模型,但对外请求失败。ETIMEDOUT 代表连接超时,ENETUNREACH 代表对应网络不可达。当时不应先删除数据库或重装容器,应先确认模型下载路径与代理。
问题二:Compose 的 environment 写法混用
错误例子:
environment:
- NODE_ENV=production
- HTTP_PROXY: http://10.144.144.1:7890这里在列表格式的 - 后写了映射对象。统一改成:
environment:
- NODE_ENV=production
- HTTP_PROXY=http://10.144.144.1:17890
- HTTPS_PROXY=http://10.144.144.1:17890
- NODE_USE_ENV_PROXY=1
- NO_PROXY=localhost,127.0.0.1,10.144.144.1同时将错误写法 - NODE_USE_ENV_PROXY="1" 改为 - NODE_USE_ENV_PROXY=1。
修改 Compose 后不能只执行 docker restart,需要重新创建容器才能载入新的环境变量:
docker compose config -q
docker compose up -d --force-recreate sillytavern问题三:代理宿主机端口与容器端口混淆
已有 mihomo 服务端口映射为:
0.0.0.0:17890 --> 7890/tcp因为 SillyTavern 通过 EasyTier 访问另一台机器的宿主机,应当使用 10.144.144.1:17890,而不是直接用内部端口 7890。即使远程地址能 ping 通,也不代表 HTTP 代理端口一定可用。
此处代理服务的实际监听地址必须可从对应 Docker 容器到达。将代理暴露为
0.0.0.0:17890时,需要限制来源,避免形成公开代理。
问题四:Node.js 是否真的走代理?
首先确认容器内的 Node.js 和环境变量:
docker exec sillytavern node -p \
"'Node: ' + process.version + ' | NODE_USE_ENV_PROXY: ' +
JSON.stringify(process.env.NODE_USE_ENV_PROXY) + ' | HTTPS_PROXY: ' +
process.env.HTTPS_PROXY"本次实测:
Node: v24.21.0 | NODE_USE_ENV_PROXY: "1" | HTTPS_PROXY: http://10.144.144.1:17890这里 JSON.stringify 输出的 "1" 正常;若出现额外转义的内层引号,则需要检查变量值。Node.js 22.21.0+ / 24.x 的支持版本可通过 NODE_USE_ENV_PROXY=1 启用内置代理功能;旧版本不能假定相同行为。
问题五:验证代理到 Hugging Face 的完整链路
第一层:宿主机经 HTTP 代理访问。
curl -vL --max-time 20 --noproxy "" \
-x http://10.144.144.1:17890 \
-o /dev/null -w '\nHTTP: %{http_code}\n' \
'https://huggingface.co/Xenova/paraphrase-multilingual-MiniLM-L12-v2/resolve/main/config.json'本次日志显示:
Connected to 10.144.144.1 port 17890
CONNECT huggingface.co:443 HTTP/1.1
HTTP/1.1 200 Connection established
HTTP/2 307
HTTP/2 200
HTTP: 200其中 307 是模型文件请求的正常重定向,-L 让 curl 跟随后得到 200。这证明代理能够访问模型配置文件,但不能保证大体积权重下载必然成功。
第二层:容器中用 Node.js fetch 访问。
docker exec sillytavern node -e "
fetch('https://huggingface.co/Xenova/paraphrase-multilingual-MiniLM-L12-v2/resolve/main/config.json', {
signal: AbortSignal.timeout(15000)
})
.then(r => console.log('HTTP:', r.status))
.catch(e => console.error('ERROR:', e))
"实测结果:
HTTP: 200第三层:在酒馆重新点“全部向量化”。
模型下载与初始化最终成功,向量化成功。这才证明本次从下载到向量生成的整体流程已经跑通。
快速诊断表
10. 日常维护、更新与备份
常用命令
# 查看服务
docker compose ps
# 实时日志
docker logs -f --tail 100 sillytavern
# 检查容器运行环境
docker exec sillytavern node -v
docker exec sillytavern printenv | grep -i proxy
# 查看映射目录
docker inspect sillytavern --format \
'{{range .Mounts}}{{println .Source "->" .Destination}}{{end}}'
# 修改 config.yaml 后重启
docker restart sillytavern
# 修改 docker-compose.yml 环境变量后重建
docker compose up -d --force-recreate sillytavern
# 更新镜像前先备份,再执行
docker compose pull sillytavern
docker compose up -d sillytavern数据备份
重要数据在 ~/ai-workstation/data/sillytavern/。备份前建议先停止服务,以减少聊天写入过程中打包产生不一致的概率:
# 在 Compose 所在目录操作
docker compose stop sillytavern
mkdir -p ~/backups
tar -czf ~/backups/sillytavern-$(date +%F-%H%M).tar.gz \
-C ~/ai-workstation/data sillytavern
docker compose start sillytavern同时备份 docker-compose.yml,以及另外保存 API 密钥(不要把密钥公开在仓库或博客里)。迁移时恢复映射目录与 Compose 后再启动即可。
经验与限制
向量记忆不是精确数据库:金额、装备数量、任务完成状态等应有可靠的独立记录。
“继续”不是精确的检索关键词:向量检索依赖周边聊天上下文,必要时可以用“导演指令”补充场景与人物。
不要将所有角色细节设为常驻:世界书过大不仅费 Token,也会和当前剧情争夺注意力。
不要频繁无检查升级
latest:尤其是正在连载的长篇小说,建议有备份、有回滚点。修改代理、模型、索引分开验证:先确认每层网络和配置正确,再考虑删缓存或重装。
11. 最终验收清单
Docker、Compose 正常工作,
sillytavern容器运行中。通过可信网络可以打开酒馆网页,并配置白名单/认证。
自定义 OpenAI 兼容接口可以连接 sub2api,并返回模型回复。
小说的角色卡、世界书、作者注释与提示词没有互相冲突。
Summarize 能生成并保存阶段摘要。
config.yaml使用正确的中文 Embedding 模型。curl经代理访问 Hugging Face 返回HTTP 200。容器内 Node.js
fetch返回HTTP 200。Vector Storage “全部向量化”成功,“查看统计数据”有向量。
已有定期备份策略,不向公网开放无保护的酒馆和代理端口。
12. 参考资料
最后一句备忘:以后再看到 Vectorization partial、fetch failed,别急着怀疑数据库。先确认 Embedding 模型、容器代理环境变量、宿主机映射端口和 Node.js 实际能否访问 Hugging Face。这里每一层都验证通过,本次故障才最终解决。