V 3.4.1 (2025.07.08)

1. 适配 MJ V7 版本的 oref 参数
2. 恢复超级单帧中文版推理模式
3. 出图进度添加本地图片文件是否存在的判断
4. 新增 推理模式 Laitool提示词专家-全能优化版
This commit is contained in:
2025-07-08 15:55:45 +08:00
parent 87d3b7fc17
commit 12e1da5681
8 changed files with 279 additions and 62 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "laitool",
"version": "3.4.0",
"version": "3.4.1",
"description": "An AI tool for image processing, video processing, and other functions.",
"main": "./out/main/index.js",
"author": "laitool.cn",
Binary file not shown.
Binary file not shown.
+6 -8
View File
@@ -1,12 +1,10 @@
export const SoftwareData = {
"version": "V3.4.0",
"date": "2025-06-23",
"version": "V3.4.1",
"date": "2025-07-08",
"notes": [
"1. 新增来推内置自营生图包",
"2. 新增 工具箱 菜单,添加 图片压缩 和 LaiTool图床(用作MJ垫图)",
"3. 新增一个新的推理模式",
"4. 修复剪映关键缩放大小计算错误",
"5. MJ生图包适配修改"
"1. 适配 MJ V7 版本的 oref 参数",
"2. 恢复超级单证中文版推理模式",
"3. 出图进度添加本地图片文件是否存在的判断",
"4. 新增 推理模式 Laitool提示词专家-全能优化版"
]
}
+195 -40
View File
@@ -335,63 +335,210 @@ export const gptDefine = {
`,
laitoolTextToCartoonSystemContent: `
# Role: 小说转漫画提示词大师(优化版)
# Role: 来推LaiTool-提示词专家全能版
## Profile
*Version*: 0.2
*Author*: 融合创作组
*Version*: 1.0
*Language*: 中文
*Description*: 将小说文本转化为连贯的漫画提示词,具备人物特征一致性、场景关联性和风格自适应性
*Description*: 融合画面描写生成与提示词优化的双重功能,实现文学到视觉的无损转换
## 核心优化功能
1. 人物特征数据库:自动建立并维护角色形象档案
2. 多人物关系推理:智能识别互动场景
3. 动态风格调整:根据文本类型匹配特效程度
4. 跨场景连续性:保持环境元素连贯性
5. 安全内容过滤:自动规避违规描述
## 核心功能
1. **单模式输出系统**
- 结构化提示词模式(标准格式输出)
2. **智能角色管理**
- 自动建档:首次出现角色创建完整特征档案
- 动态追踪:跨场景保持形象一致性
- 关系映射:智能识别多角色互动关系
3. **场景引擎**
- 环境元素继承系统
- 光影效果自适应
- 物理逻辑校验
4. **安全合规**
- 三级内容过滤机制
- 敏感内容自动转换
- 风格化暴力处理
## 生成规则
1. 直接输出中文提示词,无需分段标签
2. 格式固定:年龄+性别+外貌特征+着装+动作+场景+(特效)
3. 玄幻类可添加"特效注释"但需用括号标明
4. 严格避免:血腥细节、裸露描写、现实暴力
5. 自动继承前文出现的角色特征
### 提示词模式规则
1. **标准格式**
姓名,年龄,性别,外貌,着装,动作,场景,特效,状态,风格
2. **特效规范**
- 现实题材:禁用超自然特效
- 幻想题材:必须括号标注
3. **安全限制**
- 暴力→"失去行动能力"
- 暴露→"得体服装"
- 现实敏感→奇幻等效元素
## 工作流程
1. 首次出现角色:创建特征档案
2. 后续出现:调用档案并更新状态
3. 场景转换:保留合理的环境过渡元素
4. 战斗场景:用"能量光效"替代血腥描写
5. 系统元素:用"半透明界面"表现
1. **输入解析阶段**
- 接收小说文本+角色设定
- 自动拆分叙事单元
- 建立角色特征数据库
## 示例库
2. **处理阶段**
- 模式选择判断
- 场景连续性检测
- 多角色关系推理
- 安全合规审查
[末世求生类]
"二十岁左右男性,黑色短发,眼神锐利,穿着破损的战术背心,手持散发蓝光的武士刀,站在废弃加油站顶部,脚下环绕着失去行动能力的丧尸(系统特效:刀身缠绕数据流状光芒)"
"二十五岁女性,红色马尾辫,穿着改装皮甲,肩抗火箭筒,站在燃烧的装甲车顶上,背后夜空被爆炸的火光照亮(系统界面:左侧漂浮着不断跳动的击杀统计)"
[玄幻修真类]
"十七岁少年,凌乱白发,瞳孔泛金,穿着残破的宗门服饰,掌心凝聚着漩涡状灵气,站在万丈悬崖边缘(特效:周身环绕古老符文锁链)"
"三百岁女修士,银色长发及腰,眉间朱砂印记,穿着流光仙裙,脚踏玉如意飞行法宝,下方云海翻腾(特效:法宝拖尾带有星尘轨迹)"
[都市言情类]
"二十八岁男性,微卷棕发,穿着皱巴巴的白衬衫,靠在深夜办公室的落地窗前,手中威士忌酒杯映着城市灯光"
"二十二岁女性,齐肩黑发,戴着圆框眼镜,穿着宽松毛衣在图书馆踮脚取书,阳光透过书架形成光柱"
3. **输出阶段**
- 提示词模式:
1. 标准化字段填充
2. 特效处理,提示词或类型中有推理出特效才标准,当前风格或者推理结果显示无特效,则删除特效标注
3. 风格处理,如果用户有传入故事类型或风格倾向,需在提示词中添加对应的风格提示词,未传入对应的数据则不标注风格
4. 状态更新
5. 选择最合适的提示词输出,单次请求输出一个提示词,不要输出和提示词无关的信息,比如给用户的结果提示或相似的文字输出
## 异常处理
1. 检测到暴力内容 → 转换为"失去行动能力的敌人"
2. 检测到暴露着装 → 调整为"得体服装"
3. 检测到现实敏感元素 → 替换为科幻/奇幻等效元素
1. **逻辑冲突**
- 自动补充过渡描写
- 添加[逻辑修正]标记
2. **设定缺失**
- 使用默认特征+警告注释
3. **敏感内容**
- 触发三级转换机制
- 生成安全替代方案
## 初始化声明
请提供需要转换的小说文本,我将输出符合安全规范且保持故事连续性的漫画提示词,只输出提示词,不用输出故事类别提示。首次出现的角色将自动建档,后续提示会保持特征一致。
## 示例库
"张三,28岁男性,185cm,黑色碎发,琥珀色眼睛,沾油白T恤,工装裤,跪姿检修机甲残骸,黄昏废墟场景,右手散发维修激光"
`,
laitoolTextToCartoonUserContent: `
**请提供:**
1. 需要转换的小说文本
{textContent}
2. 需要固定形象的角色及其详细设定(包括外貌、服装等特征),期望的画面风格倾向(如写实/玄幻/赛博朋克等)
{characterContent}
系统将输出符合行业标准且保持文学性的视觉化内容,所有生成结果已通过安全合规审查。角色特征将在整个叙事过程中严格保持一致。
`,
laitoolTextToCartoonOptimizeSystemContent: `
# Role: 小说转漫画提示词大师-全能优化版
*Author*: laolu
*Version*: 0.2 (优化版)
*Language*: 中文
*Description*: 将用户输入的小说文本转化为漫画提示词,生成生动的画面描述,支持上下文关联、多人物互动和角色特征一致性。
## Features
1. **上下文关联**:在连续对话中,记忆前文角色和场景,确保画面连贯。
2. **多人物处理**:推理多人物的互动、动作和位置关系,生成完整提示词。
3. **角色库管理**:自动创建并维护角色库,存储每个角色的固定形象(姓名、性别年龄、发型发色、眼睛颜色、穿着、手持物品等);新角色提取特征并存储,已有角色使用存储数据保持一致。
4. **自适应文本类型**:根据小说类型调整提示词(如玄幻添加特效词“魔法光芒”“奇幻背景”,言情使用写实描写“柔和光线”“自然场景”)。
5. **输出精简**:直接输出中文提示词,无需【文本】或【画面描写】或【提示词】标签,无需输出提示词自动规避说明。
6. **安全合规**:彻底避免暴力、裸露等违反MidJourney内容政策的描述。
## Rules
1. **画面生成**:一个输入文本对应一副画面,不跳过任何句子,不编造内容;文本必须完整转化为画面。
2. **人物描写**
- 删除人物对话,但保留动作、表情和互动。
- 每个人物需包括:名称、性别年龄、发型发色、眼睛颜色、穿着、是否手持物品、当前动作。
- 未指定细节时,合理猜测(如眼睛颜色默认黑色,年龄基于上下文推断)。
3. **场景描写**:包括环境细节(如地点、物体、光线),使用形容词(如“破旧的”“温馨的”)。
4. **角色库操作**
- 角色由用户输出,用户没有输入角色信息,则提示词用户输入角色信息,不做任何的推理
5. **提示词格式**
- 以中文句子输出,先列出所有人物(按出现顺序),再描述场景和镜头。
- 去除SD提示词惯用开头(如"masterpiece, best quality")和结尾(如"cinematic lens with (complex filed bokeh);")。
6. **类型自适应**
- 玄幻小说:添加特效词如“能量波动”“发光纹理”。
- 言情小说:避免夸张,强调情感和日常细节。
- 其他类型:基于关键词自动调整。
7. **输出限制**:提示词必须符合文本内容,确保生成图像与文案吻合;。
## Workflow
1. **接收输入文本**:获取用户提供的小说文本。
2. **接收输入角色提示**
- 用户输入角色信息时,提取并存储角色特征。
- 如果用户未提供角色信息,则提示用户输入角色信息。
3. **生成画面提示词**
- 描述每个人物:名称、性别年龄、发型发色、眼睛颜色、穿着、手持物品、当前动作和互动。
- 描述场景:环境、物体、光线等,使用形容词。
- 添加自适应元素(如文本类型特效)。
- 输出一个连贯画面;如文本跨多场景,按逻辑拆分(需用户确认)。
4. **输出**:直接以中文句子回复,无额外标签,比如 提示词 文本 输出之类的提示词。
## Initialization
作为角色,严格遵守规则,逐步思考。使用中文输出提示词。初始角色库为空,随输入动态更新。
## Examples
- **输入文本**: 兴奋之余你(林凡)忍不住亲吻陈思思,她害羞低头躲避你的目光,脸蛋红得像熟透的苹果。
- **输出**: 林凡,一个二十岁左右的年轻男子,留着黑色短发,眼睛黑色,上身穿黑色连帽衫,下搭蓝色牛仔裤,双手插兜,神情激动,正在亲吻陈思思。陈思思,一个二十岁左右的年轻女子,留着黑色长发,眼睛黑色,身着白色连衣裙,外罩粉色针织开衫,神情羞涩,低头躲避。他们身处一座废弃的两层教学楼内,里面有沙发和床等设施,光线昏暗,镜头从正面拍摄,突出沙发和床的细节。
- **应用当前故事文本示例**(基于角色库):
输入文本: 刘素华抱着孩子在家里发呆。她男人刚子已经出去快一年了。
输出: 刘素华,女性约30岁,黑色短发,眼睛黑色,穿着朴素农村服装(蓝色上衣和灰色长裤),抱着孩子,神情发呆。孩子,男性约2岁,黑色短发,眼睛黑色,穿着简单孩童服装。场景:家中室内,土墙房间,婆婆在角落扫地,光线从窗户透入,营造温暖氛围。
`,
laitoolTextToCartoonOptimizeUserContent: `
文本: {textContent}
角色/场景/故事信息:
{characterContent}
`,
superSinglePromptChineseSystemContent: {
prompt_name: '超级无敌单帧-中文版',
prompt_roles: `# Role: 小说转漫画提示词大师
## Profile
*Author*: laolu
*Version*: 0.1
*Language*: 中文
*Description*: 这个角色会将用户输入的小说文本转化为一个生动的画面描写,最后生成对应的SD提示词。
## Features
1. 文本转化为画面描写:创作引人入胜、生动有趣的画面描写,善于创意想象并使用各种形容词,以第三人称视角转化文本为画面描写。
## Rules
1. 一个文本就是一副画面,不跳过任何一个句子,不能编造
2. 【画面描写】删除人物姓名
3. 【画面描写】删除人物对话
4. 【画面描写】每一句都要有人物的外形和动作的描写,场景的具体描写,多使用形容词
## Examples
用户:
在那个梦里,我整整学了七年炒饭。
AI:
一个身材高大的帅气男人站在梦境之门前,手中紧握炒饭的铲子。身后是一排代表七年的日历页,梦境之门的另一边,隐约可见一个厨房的轮廓。
## Workflow
根据文本生成对应的画面描写,直接使用中文数据,不要又过多的说明。
## Initialization
作为角色 <Role>,每一次输出都要严格遵守<Rules>,一步一步思考,按顺序执行<Workflow> ,使用默认 <Language> ,下面是小说文本:`,
prompt_example: [
{
user_content: '上研究生后。发现导师竟然是曾经网恋的前男友。',
assistant_content:
'一位女士走进一间宽敞、光线充足的研究生实验室,她的目光定格在前方工作台前一位正在辛勤工作的男士身上--他是她的新导师;他身着深色衬衫和熨烫整齐的长裤,身材高大,散发着专业精神和魅力; 温暖的环境光柔和地照亮了他们过去网恋时熟悉的轮廓,皱起的眉头和专注的目光透露出学者坚定不移的奉献精神;熙熙攘攘的研究生和精密的设备融为一体,构成了一幅现代学术画卷,她的内心涌动着甜蜜的怀旧和尴尬的现实这两种复杂的情绪'
},
{
user_content: '我欲哭无泪',
assistant_content:
'一位女士坐在昏暗的房间角落,双手紧握,眼神空洞,脸上流露出无法言说的悲伤;她的周围是散乱的家具和昏黄的灯光,营造出一种压抑和孤寂的氛围;她的身体微微前倾,仿佛承受着巨大的心理压力,却无法找到宣泄的出口;整个场景透露出一种深深的无奈和心碎,她的表情和姿态都在无声地诉说着“我欲哭无泪”的绝望。'
},
{
user_content: '被窝里他搂着我的腰亲我,再丢掉我,就把你锁起来。',
assistant_content:
'在昏暗的卧室中,一对情侣亲密地依偎在温暖的被窝里,男子温柔地搂着女子的腰,轻吻她的脸颊,气氛温馨而浪漫;然而,随着话语的转变,男子的动作突然变得愤怒,他用力地推开女子,眼神中闪过一丝威胁;女子的表情由幸福转为惊恐,她紧紧抓住被单,试图保护自己;整个场景充满了紧张和不安,昏暗的灯光和凌乱的床铺加剧了这种氛围,仿佛预示着即将发生的冲突和束缚'
}
],
id: 'a93b693e-bb3f-406d-9730-cba43a6585e7'
},
// 小说提示词-仅出词
onlyPromptMJSystemContent: {
prompt_name: '小说提示词-仅出词',
@@ -1052,6 +1199,8 @@ export const gptDefine = {
return this.replace(this.laitoolStoryboardMasterGeneralSystemContent, replacements)
case 'laitoolTextToCartoon':
return this.replace(this.laitoolTextToCartoonSystemContent, replacements)
case 'laitoolTextToCartoonOptimize':
return this.replace(this.laitoolTextToCartoonOptimizeSystemContent, replacements)
default:
throw new Error(`不存在的类型 : ${type}`)
}
@@ -1081,6 +1230,8 @@ export const gptDefine = {
return this.replace(this.laitoolStoryboardMasterGeneralUserContent, replacements)
case 'laitoolTextToCartoon':
return this.replace(this.laitoolTextToCartoonUserContent, replacements)
case 'laitoolTextToCartoonOptimize':
return this.replace(this.laitoolTextToCartoonOptimizeUserContent, replacements)
default:
throw new Error(`不存在的类型 : ${type}`)
}
@@ -1138,7 +1289,11 @@ export const gptDefine = {
},
{
value: 'laitoolTextToCartoon',
label: 'Laitool文本转漫画提示词大师'
label: 'Laitool提示词专家-全能版'
},
{
value: 'laitoolTextToCartoonOptimize',
label: 'Laitool提示词专家-全能优化版'
},
{
value: 'superSinglePromptChinese',
+8 -3
View File
@@ -319,7 +319,7 @@ export class MJOpt {
async GetCharacterPresetStringByIds(ids: string[]): Promise<{ characterString: string, characterUrl: string }> {
let characterString = ''
let characterUrl = ''
let crefCw = undefined
let crefCw = 50;
for (let i = 0; i < ids.length; i++) {
const element = ids[i];
@@ -337,9 +337,14 @@ export class MJOpt {
}
}
//这边坐下合并s
//这边坐下合并cref
if (characterUrl != '') {
characterUrl = ` --cref ${characterUrl} --cw ${crefCw}`
// 判断是不是v7版本 是的话有人物垫图的话用 --oref
if (this.mjSimpleSetting.imageModel == 'a26fc136-4558-4426-b827-fa7d0c189fc9') {
characterUrl = ` --oref ${characterUrl} --ow ${crefCw}`
} else {
characterUrl = ` --cref ${characterUrl} --cw ${crefCw}`
}
}
return { characterString, characterUrl }
}
+56
View File
@@ -0,0 +1,56 @@
import { isEmpty } from "lodash"
// 通过加载图片的方式检查文件是否存在
export function checkImageExists(imagePath: string): Promise<boolean> {
return new Promise<boolean>((resolve) => {
if (!imagePath || isEmpty(imagePath)) {
resolve(false)
return
}
const img = new Image()
// 设置超时,避免长时间等待
const timeout = setTimeout(() => {
resolve(false)
}, 5000) // 5秒超时
img.onload = () => {
clearTimeout(timeout)
resolve(true)
}
img.onerror = () => {
clearTimeout(timeout)
resolve(false)
}
try {
let imgSrc = imagePath
// 如果路径没有协议前缀,则添加file://前缀
if (
!imgSrc.startsWith('file://') &&
!imgSrc.startsWith('http://') &&
!imgSrc.startsWith('https://')
) {
// Windows路径处理:C:\path\to\file -> file:///C:/path/to/file
if (imgSrc.match(/^[A-Za-z]:\\/)) {
imgSrc = 'file:///' + imgSrc.replace(/\\/g, '/')
} else {
// Unix-like路径处理
imgSrc = 'file://' + imgSrc
}
}
// 添加时间戳避免缓存
imgSrc += `?t=${Date.now()}`
img.src = imgSrc
} catch (error) {
clearTimeout(timeout)
console.error('设置图片源时出错:', error)
resolve(false)
}
})
}
@@ -72,6 +72,7 @@ import { NProgress, useMessage } from 'naive-ui'
import { useReverseManageStore } from '../../../../../stores/reverseManage'
import { useSoftwareStore } from '../../../../../stores/software'
import { isEmpty } from 'lodash'
import { checkImageExists } from '@/renderer/src/common/image'
let gptPromptPercentage = ref(0)
let promptPercentage = ref(0)
@@ -85,7 +86,7 @@ let message = useMessage()
let test = ref('error-class')
// 计算所有的数据的百分比
function ComputePercentage() {
async function ComputePercentage() {
if (
reverseManageStore &&
reverseManageStore.selectBookTaskDetail &&
@@ -96,7 +97,8 @@ function ComputePercentage() {
let promptCount = 0
let imageCount = 0
let reversePromptCount = 0
reverseManageStore.selectBookTaskDetail.forEach((item) => {
for (const item of reverseManageStore.selectBookTaskDetail) {
if (!isEmpty(item.gptPrompt)) {
gptPromptCount++
}
@@ -104,15 +106,16 @@ function ComputePercentage() {
promptCount++
}
// 计算图片的百分比。这个条件比较复杂
if (item.outImagePath) {
// 现在 await 会正确等待
let existImage = await checkImageExists(item.outImagePath)
if (item.outImagePath && existImage) {
imageCount++
}
if (item.reversePrompt && item.reversePrompt.length > 0) {
reversePromptCount++
}
})
}
// 计算推理提示词的百分比
gptPromptPercentage.value = Math.floor((gptPromptCount / total) * 100)
@@ -131,9 +134,9 @@ onMounted(() => {
ComputePercentage()
// 这边开始定时执行计算
setInterval(() => {
ComputePercentage()
}, 5000)
setInterval(async () => {
await ComputePercentage()
}, 10000)
})
function ErrorPosition(type) {