后端预设、世界书部分补充

This commit is contained in:
2026-04-04 10:41:38 +08:00
parent f90ad8dc13
commit 0ae53c4b81
13 changed files with 359 additions and 4 deletions

View File

@@ -0,0 +1,15 @@
from pydantic import BaseModel, Field
class PromptComponent(BaseModel):
"""预设组件类,代表一个独立的提示词模块"""
identifier: str = Field(..., description="唯一标识符,用于引用和定位组件")
name: str = Field(..., description="组件显示名称")
content: str = Field("", description="组件内容文本")
# 0System1User2Assistant
role: int = Field(0, description="角色身份(0System1User2Assistant)")
system_prompt: bool = Field(False, description="是否强制作为系统提示词处理")
marker: bool = Field(False, description="是否为动态插入点占位符")

View File

@@ -0,0 +1,52 @@
from pydantic import BaseModel, Field
import PromptComponent
from typing import List, Dict, Any
class AIDesignSpec(BaseModel):
"""AI设计规范类包含模型生成的核心参数和动态结构配置"""
# [Base] 基础核心参数
temperature: float = Field(1.0, description="生成温度,控制随机性(0-2)")
frequency_penalty: float = Field(0.0, description="频率惩罚降低重复token概率")
presence_penalty: float = Field(0.0, description="存在惩罚,鼓励谈论新话题")
top_p: float = Field(1.0, description="核采样,控制词汇选择范围")
top_k: int = Field(0, description="随机采样范围从概率最高的K个词中选择")
top_a: float = Field(0.0, description="基于平方概率分布的采样")
min_p: float = Field(0.0, description="最小概率阈值")
repetition_penalty: float = Field(1.0, description="重复惩罚系数(1.0-1.2)")
openai_max_context: int = Field(2048, description="上下文窗口大小(Token上限)")
openai_max_tokens: int = Field(250, description="单次回复的最大长度")
max_context_unlocked: bool = Field(False, description="是否允许超出限制的上下文")
names_behavior: int = Field(0, description="名字处理行为(0=默认,1=始终包含,2=仅角色)")
send_if_empty: str = Field("", description="用户发送空消息时自动填充的内容")
impersonation_prompt: str = Field("", description="模仿模式下使用的提示词")
new_chat_prompt: str = Field("", description="开启新聊天时自动发送的系统提示")
new_group_chat_prompt: str = Field("", description="开启新群组聊天时的提示")
new_example_chat_prompt: str = Field("", description="新示例聊天的提示")
continue_nudge_prompt: str = Field("", description="续写功能触发的提示词")
bias_preset_selected: str = Field("", description="选用的偏见预设")
wi_format: str = Field("{0}", description="世界书条目的格式化字符串")
scenario_format: str = Field("{{scenario}}", description="场景描述的格式化字符串")
personality_format: str = Field("", description="角色性格的格式化字符串")
group_nudge_prompt: str = Field("", description="群组聊天中提示AI仅以特定角色回复的提示词")
stream_openai: bool = Field(True, description="是否使用流式输出")
assistant_prefill: str = Field("", description="强制AI回复的开头内容")
assistant_impersonation: str = Field("", description="模仿模式下强制AI回复的开头内容")
use_sysprompt: bool = Field(True, description="是否强制将提示词注入系统层")
squash_system_messages: bool = Field(False, description="是否压缩系统消息")
media_inlining: bool = Field(False, description="是否内联媒体描述")
continue_prefill: bool = Field(True, description="续写时是否预填充内容")
continue_postfix: str = Field(" ", description="续写时添加的后缀")
seed: int = Field(-1, description="随机种子(-1为随机)")
n: int = Field(1, description="生成回复的数量")
# [Dynamic] 动态结构
prompts: List[PromptComponent] = Field(
default_factory=list,
description="组件库,定义所有可用的积木块"
)
prompt_order: List[str] = Field(
default_factory=list,
description="组装说明书,定义构建最终提示词的顺序"
)

View File

@@ -0,0 +1,231 @@
from typing import List, Dict, Any, Optional
from pydantic import BaseModel, Field
from backend.core.models.PromptList import AIDesignSpec
from backend.core.models.PromptComponent import PromptComponent
from enum import Enum
from enum import Enum
class SpecialIdentifier(str, Enum):
"""
特殊组件标识符枚举
定义所有提示词组件的类型及其在最终 Prompt 中的默认物理流向
顺序大致遵循:系统层 -> 角色层 -> 动态层 -> 历史层 -> 尾部指令
"""
WORLD_INFO_BEFORE = "worldInfoBefore"
"""前置世界书:通常用于全局设定(如物理法则),紧接在 Main Prompt 之后,拥有最高优先级"""
PERSONA_DESCRIPTION = "personaDescription"
"""用户设定:告诉 AI {{user}} 是谁,通常放在场景之后,完成“谁在对谁说话”的闭环"""
ENHANCE_DEFINITIONS = "enhanceDefinitions"
"""增强定义:通常是 "If you have more knowledge...",用于补充 AI 的知识库这里用rag获取"""
WORLD_INFO_AFTER = "worldInfoAfter"
"""后置世界书:通常用于特定场景规则,位于中间层底部,用于覆盖或补充前面的全局设定"""
CHAT_HISTORY = "chatHistory"
"""聊天历史:包含用户与 AI 的过往对话,占据提示词的下半部分"""
JAILBREAK = "jailbreak"
"""后置指令/注释也即d0层通常位于聊天记录之后、AI 生成之前,用于最后时刻的强调(如“不要重复”)"""
class PresetAssemblyNode(BaseModel):
"""预设组装节点类,负责根据组装指令动态组装提示词内容"""
# 输入数据
design_spec: AIDesignSpec = Field(
...,
description="AI设计规范包含组件库和组装顺序"
)
target_character_id: int = Field(
...,
description="目标角色ID用于选择对应的组装指令"
)
# 内部状态(不参与序列化)
_component_map: Dict[str, PromptComponent] = Field(
default_factory=dict,
description="组件标识符到组件对象的映射"
)
def __init__(self, **data):
"""初始化方法,构建组件映射"""
super().__init__(**data)
# 构建组件映射字典,提高查找效率
self._component_map = {
comp.identifier: comp
for comp in self.design_spec.prompts
}
def _process_special_component(self, component: PromptComponent) -> Optional[Dict[str, Any]]:
"""
处理特殊组件marker为True的组件
参数:
component: 要处理的组件
返回:
Optional[Dict[str, Any]]: 处理后的消息如果组件无法处理则返回None
"""
try:
# 尝试将标识符转换为枚举
special_id = SpecialIdentifier(component.identifier)
# 根据不同标识符执行不同处理逻辑
if special_id == SpecialIdentifier.CHAT_HISTORY:
return self._handle_chat_history(component)
elif special_id == SpecialIdentifier.WORLD_INFO_BEFORE:
return self._handle_world_info_before(component)
elif special_id == SpecialIdentifier.WORLD_INFO_AFTER:
return self._handle_world_info_after(component)
elif special_id == SpecialIdentifier.CHAR_DESCRIPTION:
return self._handle_char_description(component)
else:
# 未知特殊组件,使用默认处理
return self._process_regular_component(component)
except ValueError:
# 不是特殊标识符,使用默认处理
return self._process_regular_component(component)
def _process_special_component(self, component: PromptComponent) -> Optional[Dict[str, Any]]:
"""
处理特殊组件marker为True的组件
参数:
component: 要处理的组件
返回:
Optional[Dict[str, Any]]: 处理后的消息如果组件无法处理则返回None
"""
try:
# 尝试将标识符转换为枚举
special_id = SpecialIdentifier(component.identifier)
# 根据不同标识符执行不同处理逻辑
if special_id == SpecialIdentifier.CHAT_HISTORY:
return self._handle_chat_history(component)
elif special_id == SpecialIdentifier.WORLD_INFO_BEFORE:
return self._handle_world_info_before(component)
elif special_id == SpecialIdentifier.WORLD_INFO_AFTER:
return self._handle_world_info_after(component)
elif special_id == SpecialIdentifier.DIALOGUE_EXAMPLES:
return self._handle_dialogue_examples(component)
elif special_id == SpecialIdentifier.CHAR_DESCRIPTION:
return self._handle_char_description(component)
elif special_id == SpecialIdentifier.CHAR_PERSONALITY:
return self._handle_char_personality(component)
elif special_id == SpecialIdentifier.SCENARIO:
return self._handle_scenario(component)
elif special_id == SpecialIdentifier.PERSONA_DESCRIPTION:
return self._handle_persona_description(component)
else:
# 未知特殊组件,使用默认处理
return self._process_regular_component(component)
except ValueError:
# 不是特殊标识符,使用默认处理
return self._process_regular_component(component)
def _process_regular_component(self, component: PromptComponent) -> Dict[str, Any]:
"""
处理普通组件marker为False的组件
参数:
component: 要处理的组件
返回:
Dict[str, Any]: 处理后的消息
"""
# 角色映射表
role_map = {0: "system", 1: "user", 2: "assistant"}
# 构建消息
message = {
"role": role_map.get(component.role, "system"),
"content": component.content
}
# 添加系统提示词标记
if component.system_prompt:
message["system_prompt"] = True
return message
# 以下为特殊组件处理方法
def _handle_chat_history(self, component: PromptComponent) -> Dict[str, Any]:
"""
处理聊天历史组件
参数:
component: 聊天历史组件
返回:
Dict[str, Any]: 处理后的消息
"""
# 这里应该从外部获取实际的聊天历史
# 示例实现,实际需要根据业务逻辑调整
return {
"role": "system",
"content": "聊天历史内容...",
"marker": True,
"type": "chat_history"
}
def _handle_world_info_before(self, component: PromptComponent) -> Dict[str, Any]:
"""
处理前置世界信息组件
参数:
component: 世界信息组件
返回:
Dict[str, Any]: 处理后的消息
"""
# 这里应该从外部获取实际的世界信息
return {
"role": "system",
"content": "前置世界信息...",
"marker": True,
"type": "world_info_before"
}
def _handle_world_info_after(self, component: PromptComponent) -> Dict[str, Any]:
"""
处理后置世界信息组件
参数:
component: 世界信息组件
返回:
Dict[str, Any]: 处理后的消息
"""
# 这里应该从外部获取实际的世界信息
return {
"role": "system",
"content": "后置世界信息...",
"marker": True,
"type": "world_info_after"
}
def _handle_char_description(self, component: PromptComponent) -> Dict[str, Any]:
"""
处理角色描述组件
参数:
component: 角色描述组件
返回:
Dict[str, Any]: 处理后的消息
"""
# 这里应该从外部获取实际的角色描述
return {
"role": "system",
"content": "角色描述内容...",
"marker": True,
"type": "char_description"
}

View File

@@ -3,6 +3,10 @@ import React from 'react';
import './SideBarLeft.css';
import { useSideBarLeftStore } from '../../Store/indexStore';
import useSideBarRightStore from '../../Store/Slices/SideBarLeftSlice';
import Gallery from './tab/Gallery';
import ApiConfig from './tab/ApiConfig';
import Presets from './tab/Presets';
import WorldBook from './tab/WorldBook';
const SideBarLeft = () => {
const { activeTab, tabs, setActiveTab } = useSideBarLeftStore();
@@ -22,10 +26,10 @@ const SideBarLeft = () => {
</div>
<div className="sidebar-content">
{activeTab === 'gallery' && <div className="tab-content">画廊内容</div>}
{activeTab === 'api' && <div className="tab-content">API配置内容</div>}
{activeTab === 'presets' && <div className="tab-content">预设配置内容</div>}
{activeTab === 'worldbook' && <div className="tab-content">世界书内容</div>}
{activeTab === 'gallery' && <Gallery />}
{activeTab === 'api' && <ApiConfig />}
{activeTab === 'presets' && <Presets />}
{activeTab === 'worldbook' && <WorldBook />}
</div>
</div>
);

View File

@@ -0,0 +1,13 @@
import React from 'react';
import '../tabcss/ApiConfig.css';
const ApiConfig = () => {
return (
<div className="api-config-content">
<h2>API配置</h2>
{/* 在这里实现API配置的具体内容 */}
</div>
);
};
export default ApiConfig;

View File

@@ -0,0 +1,13 @@
import React from 'react';
import '../tabcss/Gallery.css';
const Gallery = () => {
return (
<div className="gallery-content">
<h2>画廊</h2>
{/* 在这里实现画廊的具体内容 */}
</div>
);
};
export default Gallery;

View File

@@ -0,0 +1,13 @@
import React from 'react';
import '../tabcss/Presets.css';
const Presets = () => {
return (
<div className="presets-content">
<h2>预设配置</h2>
{/* 在这里实现预设配置的具体内容 */}
</div>
);
};
export default Presets;

View File

@@ -0,0 +1,13 @@
import React from 'react';
import '../tabcss/WorldBook.css';
const WorldBook = () => {
return (
<div className="worldbook-content">
<h2>世界书</h2>
{/* 在这里实现世界书的具体内容 */}
</div>
);
};
export default WorldBook;

View File

@@ -0,0 +1 @@
WorldBook.css