摘要:Luker是基于SillyTavern(酒馆)二次开发的角色扮演聊天软件,并做了大量功能优化和改进,完全兼容SillyTavern数据。针对酒馆全量保存数据、烧流量等问题,Luker采用增量patch端点和后端实时存储,大幅减少传输量并防止消息丢失。此外还提供多Agent编排、记忆图、角色卡编辑助手等内置插件,支持角色卡绑定专属预设、世界书激活链路追踪、安卓APP、GitHub/Discord登录等功能。

前言

SillyTavern,中文圈内俗称酒馆。一款用于角色扮演的LLM聊天软件。

理论上也可以普通聊天,但我说实话这个体验真不行吧,不如其他LLM聊天软件实现

酒馆的设计有很多让人费解的地方,就拿发送对话消息的流程举例吧,我让AI给我画个Mermaid看看:

sequenceDiagram
    autonumber
    participant U as 👤 用户
    participant F as 📱 前端
    participant B as 🖥️ 后端
    participant L as 🤖 LLM端点

    U->>F: 发送消息
    F->>B: 转发用户消息
    B->>L: 请求LLM响应
    L-->>B: 流式返回响应
    B-->>F: 转发消息流
    
    Note over F: 等待完整接收消息...
    
    F->>B: 📦 重传全部聊天记录
    B->>B: 完整重新保存聊天记录
    B-->>F: 保存成功确认

    rect rgb(255, 200, 200)
        Note over F,B: ⚠️ 问题:前端中断 = 整个流程失败
        Note over F,B: ⚠️ 消息丢失,无法恢复
    end

每次对话要来回倒腾整个聊天文件,这很不优雅。尤其对云端部署酒馆的用户,非常烧流量。

酒馆的绝大部分保存的API设计上都是全量保存的:世界书是一整本保存、插件和用户设置每次都全量保存、消息编辑也是全量保存...

非常不优雅。而且真烧我的流量! quyinniang-heng.png

Luker的改进

为了优化酒馆的体验,我在酒馆的基础上做了二次开发,开发了Luker
就拿前面的消息发送流程,Luker的改动是这样的:

sequenceDiagram
    autonumber
    participant U as 👤 用户
    participant F as 📱 前端
    participant B as 🖥️ 后端
    participant L as 🤖 LLM端点
    participant DB as 💾 数据库

    U->>F: 发送消息
    F->>B: 转发用户消息
    B->>DB: 保存用户消息
    B->>L: 请求LLM响应
    
    L-->>B: 流式返回响应
    
    par 并行处理
        B-->>F: 转发消息流
    and
        B->>DB: 实时/增量存储AI响应
    end
    
    Note over F: 接收消息
    Note over F: ✅ 确认后端已保存
    Note over F: ✅ 无需重传全量记录

    rect rgb(200, 255, 200)
        Note over F,B: ✅ 前端中断不影响数据
        Note over F,B: ✅ 刷新页面可恢复会话
    end

这样就避免了聊天记录在前后端之间反复折腾的问题。

不仅如此,Luker改造了许多SillyTavern的API,世界书、聊天记录、用户设置等内容的保存统一优先使用Luker新增的patch端点,该端点遵循RFC 6902标准,尽可能地避免了数据的全量传输。以前开关一个插件里的设置就能传3M的流量,现在连200字节都不要。并且保存是延迟触发,尽可能地避免冲突。

对于插件创作者,Luker还尽可能地提高了SillyTavern的扩展能力,具体地讲:

  • Luker允许插件以非常简单的方法复用用户已有的API预设和聊天补全预设
  • Luker还内置了几个额外的插件:多Agent编排、记忆图插件、角色卡编辑助手、Hook顺序

对于角色卡开发者,Luker提供了一些很方便的能力:

  • 你可以追踪某个世界书条目的激活链路,看看到底是谁激活了本不该激活的世界信息
  • Luker的角色卡编辑助手也允许LLM直接操作角色卡的信息、角色卡绑定的世界书信息
  • Luker的角色卡可以绑定专属的人设和聊天补全预设,角色卡的开发者不必再让用户手动导入专属预设,也不必把用户人设放在水土不服的世界书里了!绑定在角色卡上的人设和预设是独立的,不会污染全局的人设列表和预设信息,关闭角色卡聊天会自己消失,并且可随角色卡导入导出

对于普通用户:

  • Luker的多Agent插件允许你的消息经过多Agent分析、剧情编排等流程,并且该流程是可自定义的,还可以让AI给你生成专属于角色卡的编排,并随角色卡导出。多Agent编排理论上很适合需要复杂思考的场景,用以替代单轮回复中的思维链,但比较烧token
  • 更新角色卡的时候,角色卡编辑助手会自动弹出提示,询问是否需要更新世界书,并且可以让AI帮你分析世界书的变动,任何你对世界书的二改都可以由AI帮你方便地迁移到新版角色卡的世界书中
  • Luker的记忆图插件采取了一种类似图的数据结构来存储角色扮演的数据:由多种不同类型的结点和边构成一个完整的图,包含了角色扮演的历史剧情。在每轮消息前,插件会调用LLM,根据你的输入,自动地在图中深挖、检索,试图找出最有关联的事件、任务、人物结点,并注入到负责创作的LLM上下文中
  • Luker支持安卓APP!你可以在安卓APP上直接使用Luker,而不必依赖云服务器和Termux手跑nodejs
  • 管理员可以在Luker前端上直接查看后端的日志
  • API预设和聊天补全预设解耦,切换一个不会连带着切换另一个,可自由搭配LLM和破限

对于站长:

  • Luker支持配置GitHub/Discord登录,并可为每位用户限制空间大小的配额。Discord登录可额外要求用户必须在某个服务器中/拥有某个身份组

如何使用?

用法和SillyTavern是完全一样的,并且完全兼容SillyTavern的数据。如果你不想用Luker了,直接降级回SillyTavern,也是完全可以的,数据不会被破坏。但仍然建议做好备份,我不为数据丢失负责。

你可以在GitHub Release中找到Luker最新版Release的APK:https://github.com/funnycups/Luker/releases/latest

Docker也可以用,仓库内已经提供了现成的docker-compose.yml参考:

services:
  luker:
    image: ghcr.io/funnycups/luker:latest
    container_name: luker
    ports:
      - 127.0.0.1:8000:8000
    volumes:
      - ./plugins:/home/node/app/plugins
      - ./config:/home/node/app/config
      - ./data:/home/node/app/data
      - ./extensions:/home/node/app/public/scripts/extensions/third-party
    restart: unless-stopped

插件介绍

下面介绍一下Luker自带的几个插件的用法。

记忆图

感谢数据库项目,本插件的设计思路受数据库启发:https://discord.com/channels/1134557553011998840/1429151492362862683

TL;DR

记忆图的配置非常直观,大部分设置项都是无二义的。

默认配置即开即用,你只需要设置一下“召回API预设”、“召回预设”、“写入API预设”、“写入预设”。

关于API预设和聊天补全预设的注意事项,可参考关于预设设置

什么是记忆图

想象一个图,它由许多不同类型的结点构成:事件结点、主线结点、角色结点、地点结点、世界规则结点。

一个图如何表达完整的事件呢,这是通过边和结点共同实现的。举例来讲,第零层发生了一个事件,第一层发生了一个事件,第二次又一个事件。而三个事件又分别牵扯到不同的人和不同的地点。那么这个图就是这样的结构(下面的剧情示例都是LLM生成的,不要在乎剧情 zanghu.png ):

flowchart RL
  %% 从右到左:事件1 -> 事件2 -> 事件3

  E1["事件1
summary: 在港口达成交易
status: resolved"] E2["事件2
summary: 抵达遗迹并触发机关
status: ongoing"] E3["事件3
summary: 队伍分裂并形成新目标
status: blocked"] E1 --> E2 --> E3 C1["角色结点
Mira"] L1["地点结点
旧港口"] R1["世界规则结点
血契代价"] C2["角色结点
守墓人"] L2["地点结点
失落遗迹"] T1["主线结点
追查血契"] C3["角色结点
向导"] L3["地点结点
地下回廊"] T2["主线结点
重组队伍"] E1 --- C1 E1 --- L1 E1 --- R1 E2 --- C2 E2 --- L2 E2 --- T1 E3 --- C3 E3 --- L3 E3 --- T2

结点的压缩

你可能要问了:这事件结点和常说的“小总结”有什么区别吗?

结点有个属性,叫做“层级压缩”。具有这个属性的结点是可以向上压缩的。压缩后的结点大概长这样:

flowchart TB
  subgraph L2["二级压缩层"]
    direction RL
    C12["二级事件压缩1"]
  end

  subgraph L1["一级压缩层"]
    direction RL
    C1["一级事件压缩1"]
    C2["一级事件压缩2"]
    C3["一级事件压缩3"]
  end

  subgraph RAW["原始事件层"]
    direction RL
    E1["事件1"] --> E2["事件2"] --> E3["事件3"] --> E4["事件4"] --> E5["事件5"] --> E6["事件6"] --> E7["事件7"] --> E8["事件8"] --> E9["事件9"]
  end

  C12 --> C1
  C12 --> C2

  C1 --> E1
  C1 --> E2

  C2 --> E3
  C2 --> E4

  C3 --> E5
  C3 --> E6

虽然原始的事件是1~9,但由于事件结点是可压缩的,事件1~事件4被压缩为更高层的一级事件压缩1和2,事件5和6被压缩为更高层的二级事件压缩3。而一级事件压缩1和2又被进一步压缩为二级事件压缩1。最终,只有二级事件压缩1、一级事件压缩3、事件7~9会被注入创作LLM。

任何被配置为“启用层级压缩”的常驻注入结点(默认配置中,只有event和thread结点是这个配置),其压缩和注入的思路都如本节所述。

记忆召回与注入

在图中,有些结点是常驻注入的,比如事件结点和主线结点;有些结点则是需要记忆召回流程才能注入的,比如角色结点。

这意味着,最终,在负责创作故事的LLM的上下文中,它可以看到完整的所有事件结点(其实并不是全部,因为事件结点有向上压缩的机制,后面会讲),但只有被召回的角色结点的信息才能被它看到。

那么,什么是召回?

简单来讲,有一个专门的LLM负责分析你的输入和上下文的几轮对话,并在图的结构中探索。它会选择最有价值的一些结点,并把这些结点注入到创作故事的LLM的上下文中。

比如我们聊了几个楼层:

楼层1:用户与Mira在旧港口接触线人,确认“血契”与失落遗迹有关。
楼层2:双方用一件稀有材料换到遗迹入口坐标,并得知“强行破门会触发代价”。
楼层3:队伍进入遗迹后触发机关,守墓人现身阻拦,现场陷入混乱。
楼层4:撤离过程中队伍分裂,Mira与用户短暂失联;主线目标从“深入探索”变成“先重组队伍”。

然后我现在输入:

我继续前进,寻找Mira。

召回模型会看到剧情的上下文、用户最新输入、以及整个图的状态。
最终,召回模型决定选择下面这些结点召回:

  • Mira(当前状态/目标)
  • 向导(当前协作状态)
  • 地下回廊(本轮行动所在区域)
  • 失落遗迹(大场景危险背景)
  • 重组队伍(当前短期主线)

于是,负责创作的LLM最终看到的数据是这样的:

[Table: Core event_table]
| summary | status |
| 在港口达成交易并拿到坐标 | resolved |
| 进入遗迹后触发机关 | ongoing |
| 队伍分裂,行动目标转为先汇合 | blocked |

[Table: Core rule_table]
| title | constraint | scope | status |
| 血契代价 | 禁术会支付代价,不能硬破封印 | 遗迹区域 | active |

[Table: Recall character_table]
| name | state | goal |
| Mira | 警惕,短暂失联 | 尽快与队伍汇合 |
| 向导 | 紧张但可配合 | 持火把引路并保持静默 |

[Table: Recall location_table]
| name | danger | state |
| 地下回廊 | 高 | 走廊机关仍有余光触发 |
| 失落遗迹 | 高 | 守墓人活动频繁 |

[Table: Recall thread_table]
| title | summary | status |
| 重组队伍 | 先汇合,再继续追查血契 | active |

可以看到,常驻的记忆是始终注入的(Core),而非常驻的记忆则根据LLM的召回选择被注入(Recall)。从而在节省上下文的同时尽可能地提供整个聊天中涉及到的信息。

召回LLM、边与事件压缩

被压缩的结点和边在召回过程中有什么用呢?

召回LLM可以看到这些结点的边,从而直观地理解不同结点之间的关联。

对于被压缩的结点:召回LLM最开始看到的结点与创作LLM一样——它不能看到被高层压缩结点隐藏的事件结点。

召回LLM可以通过有限轮的深挖,每次选择一批结点,它可以看到这个结点的儿子(被压缩的结点),以及这些儿子结点的边。经过有限轮的深挖,召回LLM最终根据一个局部的图的结构,决定到底召回哪些结点。

让AI举个例子吧:

例子:找回失联队友 Mira

  1. 当前用户输入
    “我贴着墙前进,压低声音叫 Mira,准备先汇合再继续任务。”
  2. 召回LLM初始能看到的结点(还看不到被压缩隐藏的子事件)
    摘要A(压缩结点)、Mira、地下回廊、主线:重组队伍
  3. 初始能看到的边
    摘要A --涉及--> Mira
    摘要A --发生于--> 地下回廊
    摘要A --推进--> 主线:重组队伍
  4. 第1轮深挖(召回LLM选择深挖“摘要A”)
    现在展开看到子事件:事件1 触发机关、事件2 队伍分裂、事件3 Mira失联
    并看到这些子事件各自的边(例如 事件3 -> Mira、事件2 -> 主线:重组队伍)。
  5. 第2轮深挖(只深挖最相关子事件)
    召回LLM继续看 事件3 Mira失联 的邻接边,确认它和“当前用户动作(呼唤Mira、先汇合)”直接相关。
  6. 最终召回结果(用于注入)
    选择:事件3 Mira失联、Mira、地下回廊、主线:重组队伍
    不选择:事件1 触发机关(本轮相关性较低)

查看召回的结果

记忆图插件中,有个“查看最近注入”,点击可查看最近的召回结果。

注意:同一条消息,在页面没有刷新、内容没有变动的情况下,重新生成将会直接复用之前的召回结果。


多智能体编排

TL;DR

顾名思义,它会在你消息发送前调用多个Agent或并行或串行地进行剧情编排和分析,最终产出一份编排指导注入到创作LLM的上下文中,让它写出更高质量的回复。

默认配置即开即用,你只需要设置"LLM节点API预设"和"LLM节点提示词预设"。关于API预设和聊天补全预设的注意事项,可参考关于预设设置

多Agent编排的运行顺序天然地在记忆召回之后,因此它可以看到所有召回的、有价值的记忆。

它在做什么

你发一条消息,创作LLM开始写回复。但在它动笔之前,编排插件会先跑一轮剧情编排分析。

默认的编排是这样的:

  1. 蒸馏器读取最近的聊天记录和你的最新输入,提炼出当前场景状态、用户意图等。
  2. 世界书读取器反数据化守卫等约束agent并行工作:前者提取当前生效的世界书硬约束,后者审查是否存在报告体、数据化措辞等违规风格。这些约束agent会规范后续结点的能力。
  3. 规划器记忆分析器并行工作:前者规划下一步剧情走向,后者筛选哪些被召回的记忆值得在本轮使用。
  4. 审查者串行审查上一层所有工作节点的产出,逐项检查连续性、因果性、角色一致性、反OOC、世界书约束、反数据化等硬性要求。通过则放行,不通过则要求特定节点重跑。
  5. 合成器将所有通过审查的产出合并为一份简洁、可直接用于创作的编排指导。
flowchart LR
  subgraph S1["阶段1: distill"]
    direction TB
    D["蒸馏器
distiller"] end subgraph S2["阶段2: grounding"] direction TB LR["世界书读取器
lorebook_reader"] ADG["反数据化守卫
anti_data_guard"] end subgraph S3["阶段3: reason"] direction TB P["规划器
planner"] RR["记忆相关性
recall_relevance"] end subgraph S4["阶段4: review"] direction TB C["审查者
critic"] end subgraph S5["阶段5: finalize"] direction TB SY["合成器
synthesizer"] end S1 --> S2 --> S3 --> S4 --> S5

默认编排只是一个参考,你可以自己编写编排,也可以使用AI快速生成/多轮对话迭代产生编排。

除了全局编排,编排也可以绑定到特定角色卡上,为特定角色卡创建独特的编排,这些编排可随角色卡导出,并被其他人导入

三种执行模式

编排插件提供三种执行模式,适用于不同场景:

Spec工作流(默认)

按预定义的阶段(stage)和节点(node)顺序执行。每个阶段包含若干节点,阶段内可串行或并行。这是最可控、最透明的模式。

单Agent模式

只用一个Agent完成所有编排工作。适合模型能力强、不想消耗太多token的场景。配置简单,只需设置系统提示词和用户提示词模板。

Agenda规划器

由一个Planner Agent维护待办列表,动态决定调度哪些Agent、何时结束。Planner可以并行派发多个独立任务,也可以串行深挖。这是最强大自由的模式,比较接近其他Agent软件的实现

工作流编辑

在Spec模式下,你可以完全自定义工作流的结构。

阶段(Stage)是执行的基本单元。每个阶段有一个执行方式:

  • 串行:节点按顺序依次执行
  • 并行:节点同时执行

节点(Node)是阶段内的具体工作单元。每个节点有:

  • 节点ID:唯一标识符
  • 预设:指向一个Agent预设,定义该节点的系统提示词和用户提示词模板
  • 节点类型:Worker(工作节点)或Review(审查节点)

审查节点有特殊行为:它不产出内容,而是审查上一层工作节点的产出,决定"通过"或"要求重跑"。

Agent预设定义了每个节点的行为。每个预设包含:

  • 系统提示词:告诉Agent它的角色和职责
  • 用户提示词模板:每次执行时填充的模板,支持以下占位符:

    • {{recent_chat}}:最近的聊天记录
    • {{last_user}}:用户最新输入
    • {{distiller}}:蒸馏器的产出
    • {{previous_outputs}}:前序节点的产出

上一轮的编排结果会自动注入到每个节点的模板之前,无需手动引用。

编排结果的注入

编排完成后,最终的指导文本会被注入到创作LLM的上下文中。你可以配置注入位置:

  • 角色定义前/后
  • 作者注释前/后
  • 示例消息前/后
  • 聊天深度(可指定深度值和角色)

默认注入在聊天深度0、System角色。你还可以设置一条自定义指令,会被放在编排结果之前,例如“先遵循下列指导,再用角色语气完成最终回复。”

编排结果的复用

编排结果会绑定到触发它的用户消息楼层。当你执行继续、重新生成、滑动等操作时,如果用户消息没有变化,插件会直接复用上一次的编排结果,不会重新跑一轮Agent。

只有当用户消息内容发生变化(比如你编辑了消息),才会重新执行编排。

AI生成编排配置

不想手动配置工作流?插件提供两种AI辅助方式:

AI快速生成:一键为当前角色卡生成定制的编排配置。AI会分析角色卡内容,设计合适的阶段、节点和预设。你可以在“AI生成目标”中填写额外要求,比如“悬疑节奏、严格角色内表达”。

AI迭代工作台:打开一个对话式界面,与AI反复讨论和调整编排配置。AI提出的每一步修改都需要你审批后才会生效,支持查看变更diff。你可以在对话中不断提出新的优化需求。还可以要求模型“以xxx作为用户最新输入,模拟一轮编排,看看效果如何”。

查看运行结果

  • 查看最近一轮:查看最近一次编排的最终注入文本和绑定的用户楼层。你也可以手动编辑最近一轮的编排结果文本。
  • 查看运行态轨迹:查看完整的执行过程,包括流程图、执行时间线、每个节点的执行次数和产出、审查重跑记录等。

注意:运行态轨迹仅保存在内存中,切换聊天时会清空。


角色编辑助手

TL;DR

角色卡编辑助手让你通过自然语言对话来编辑角色卡和世界书,而不是手动翻找字段。它还能在你替换/更新角色卡时,智能处理世界书的同步问题。

对话式编辑器

点击"打开编辑器",会弹出一个对话界面。你可以用自然语言告诉AI你想怎么改角色卡,比如:

"把角色的性格描述改得更内向一些"
"在世界书里新增一个关于魔法体系的条目,关键词设为'魔法'和'法术'"
"删除世界书里UID为3的条目"
"查一下世界书里有没有关于'龙'的条目"

AI会通过工具调用来执行这些操作。每一批修改都会先展示diff供你审批,你可以逐条通过或拒绝。

AI可以使用的工具包括:

  • 更新角色卡字段:修改角色名、描述、性格、第一条消息、场景等
  • 设置主世界书:绑定或更换角色卡的主世界书
  • 新增/更新世界书条目:创建或修改世界书条目的内容、关键词、激活逻辑等
  • 删除世界书条目:按UID删除指定条目
  • 查询世界书条目:按关键词搜索条目,支持按激活关键词或全文搜索
  • 获取世界书条目详情:按UID列表获取条目的完整内容
  • 联网搜索:使用搜索插件暴露的搜索工具搜索和访问网页资料,创作同人卡应该很有帮助

修改历史与回滚

每一次通过审批的修改都会记录在历史中。你可以:

  • 查看每条历史记录的diff(修改前后对比)
  • 回滚到任意一条历史记录的状态
  • 删除单条记录或清空全部历史

历史记录保存在角色卡的sidecar数据中,跟随角色卡存在,但不会随角色卡被导出。

世界书同步

当你通过"替换"或"更新"操作导入新版本的角色卡时,角色卡绑定的世界书可能也发生了变化。编辑助手会自动检测这种情况,并弹出同步弹窗,提供三种处理方式:

模型分析后更新

AI会对比新旧世界书的差异,分析每个条目的变化(新增、修改、删除),然后生成一批同步操作供你审批。你可以在审批前补充额外要求,比如"保留旧版本中关于XX的条目"。

直接替换

不经过分析,直接用新角色卡携带的世界书替换旧的。简单粗暴但快速。

不替换

取消本次世界书变更,恢复到导入前的世界书绑定(这是原版SillyTavern的默认行为)。

注意:酒馆助手对世界书替换有类似的功能,建议关闭酒馆助手中相关的开关以便冲突。

搜索插件

TL;DR

搜索插件为Luker提供联网搜索能力。它有两种工作方式:作为创作LLM的可调用工具,或作为预请求Agent在生成前自动搜索并将结果写入世界书。

默认配置即开即用(DuckDuckGo无需API Key),你只需要启用插件即可。

两种工作模式

工具模式

启用后,创作LLM在生成回复时可以主动调用搜索和访问网页的工具。适合LLM自己判断“我需要查一下这个信息”的场景。比如,纯粹和LLM对话聊天查资料啥的。

预请求Agent模式

启用后,在每次生成前会自动运行一个搜索Agent。这个Agent会:

  1. 分析当前聊天上下文和用户最新输入
  2. 判断是否需要搜索新信息
  3. 如果需要,执行搜索和网页访问
  4. 将搜索结果整理为世界书条目,写入一个专用的共享世界书(__SEARCH_TOOLS__)
  5. 这些条目会在后续生成中作为世界书内容注入创作LLM的上下文

Agent的核心原则是忠于源文本:它只记录从搜索结果中获取的客观事实,不会添加剧情指导、角色行为建议或任何创作性内容。每个世界书条目都像一条参考笔记,而不是写作指令。Gemini有点蠢所以可能不听这个指示,会把所有结果和实际剧情发展融合

世界书条目管理

Agent会根据信息的性质自动选择合适的激活方式。比如用户提到一个具体角色名,Agent会创建以该角色名为关键词的条目;而如果涉及通用的世界观设定,Agent可能会创建常驻注入的条目。

搜索结果的复用

与编排插件类似,搜索Agent的结果也会绑定到触发它的用户消息楼层。继续、重新生成、滑动等操作会复用已有结果,不会重复搜索。

只有当用户消息内容发生变化时,才会重新执行搜索Agent。

与其他插件的协作

搜索插件会将自己的工具定义暴露为全局API(Luker.searchTools),其他插件(比如角色卡编辑助手)可以直接调用搜索和访问网页的能力,无需重复实现。

这个全局API不依赖前面两种工作方式的开关。

关于预设设置

Luker的插件有两类预设设置:一类是API预设,一类是聊天补全预设。

API预设的设置很直观。你希望这个插件的功能用哪个API,你就给它设置这个API的预设即可。

聊天补全预设通常建议用一个比较精简的破限。它的原理很简单:插件传入的任务指令会被替换为聊天补全预设的Chat History内容,复用其他结构,包括破限、世界书等内容。插入特定聊天深度的提示词会被单独保留。

如果你希望使用自己平常用的破限,也没问题。但建议把一些破限无关的提示词条目设置为extra,就像下面这样:
extra提示词

这样的提示词就会被自然地排除在插件的提示词之外,但又会被最终创作的LLM看到。这样可以避免预设里的一些条目误导LLM,让它们无法完成插件给出的任务。

本文作者:小欢

本文链接:Luker:更加优雅的SillyTavern实现 - https://www.cups.moe/archives/luker.html

版权声明:如无特别声明,本文即为原创文章,仅代表个人观点,版权归 小欢博客 所有,遵循知识共享署名-相同方式共享 4.0 国际许可协议。转载请注明出处!