feat: add system config item for reward image, add app config item to use custom text2img param json file

This commit is contained in:
RockYang 2023-10-08 17:48:50 +08:00
parent 0270ec26fb
commit fbd599194c
9 changed files with 296 additions and 131 deletions

View File

@ -34,7 +34,7 @@ func NewDefaultConfig() *types.AppConfig {
}, },
}, },
MjConfig: types.MidJourneyConfig{Enabled: false}, MjConfig: types.MidJourneyConfig{Enabled: false},
SdConfig: types.StableDiffusionConfig{Enabled: false}, SdConfig: types.StableDiffusionConfig{Enabled: false, Txt2ImgJsonPath: "res/text2img.json"},
WeChatBot: false, WeChatBot: false,
} }
} }

View File

@ -45,6 +45,7 @@ type StableDiffusionConfig struct {
Enabled bool Enabled bool
ApiURL string ApiURL string
ApiKey string ApiKey string
Txt2ImgJsonPath string
} }
type AliYunSmsConfig struct { type AliYunSmsConfig struct {
@ -112,4 +113,5 @@ type SystemConfig struct {
EnabledRegister bool `json:"enabled_register"` EnabledRegister bool `json:"enabled_register"`
EnabledMsg bool `json:"enabled_msg"` // 启用短信验证码服务 EnabledMsg bool `json:"enabled_msg"` // 启用短信验证码服务
EnabledDraw bool `json:"enabled_draw"` // 启动 AI 绘画功能 EnabledDraw bool `json:"enabled_draw"` // 启动 AI 绘画功能
RewardImg string `json:"reward_img"` // 众筹收款二维码地址
} }

203
api/res/text2img.json Normal file
View File

@ -0,0 +1,203 @@
{
"fn_index": 405,
"data": [
"task(x690lsugziqd8x9)",
"A chinese girl Walking the streets of ancient China",
"",
[],
20,
"DPM++ 2M Karras",
false,
false,
1,
1,
7,
-1,
-1,
0,
0,
0,
false,
256,
256,
false,
0.7,
2,
"Latent",
0,
0,
0,
[],
"None",
false,
"MultiDiffusion",
false,
10,
1,
1,
64,
false,
true,
1024,
1024,
96,
96,
48,
1,
"None",
2,
false,
false,
false,
false,
false,
0.4,
0.4,
0.2,
0.2,
"",
"",
"Background",
0.2,
-1,
false,
0.4,
0.4,
0.2,
0.2,
"",
"",
"Background",
0.2,
-1,
false,
0.4,
0.4,
0.2,
0.2,
"",
"",
"Background",
0.2,
-1,
false,
0.4,
0.4,
0.2,
0.2,
"",
"",
"Background",
0.2,
-1,
false,
0.4,
0.4,
0.2,
0.2,
"",
"",
"Background",
0.2,
-1,
false,
0.4,
0.4,
0.2,
0.2,
"",
"",
"Background",
0.2,
-1,
false,
0.4,
0.4,
0.2,
0.2,
"",
"",
"Background",
0.2,
-1,
false,
0.4,
0.4,
0.2,
0.2,
"",
"",
"Background",
0.2,
-1,
false,
false,
true,
true,
false,
1536,
96,
false,
false,
"LoRA",
"None",
1,
1,
"LoRA",
"None",
1,
1,
"LoRA",
"None",
1,
1,
"LoRA",
"None",
1,
1,
"LoRA",
"None",
1,
1,
null,
"Refresh models",
null,
null,
null,
null,
false,
false,
"positive",
"comma",
0,
false,
false,
"",
"Seed",
"",
"Nothing",
"",
"Nothing",
"",
true,
false,
false,
false,
0,
null,
false,
null,
false,
null,
false,
null,
false,
50,
[],
"",
"",
""
],
"event_data": null,
"session_hash": "fxz5yw7n1a4"
}

View File

@ -8,11 +8,13 @@ import (
"chatplus/store/vo" "chatplus/store/vo"
"chatplus/utils" "chatplus/utils"
"context" "context"
"encoding/json"
"fmt" "fmt"
"github.com/go-redis/redis/v8" "github.com/go-redis/redis/v8"
"github.com/imroc/req/v3" "github.com/imroc/req/v3"
"gorm.io/gorm" "gorm.io/gorm"
"io" "io"
"os"
"strconv" "strconv"
"time" "time"
) )
@ -85,11 +87,18 @@ func (s *Service) PushTask(task types.SdTask) {
// Txt2Img 文生图 API // Txt2Img 文生图 API
func (s *Service) Txt2Img(task types.SdTask) error { func (s *Service) Txt2Img(task types.SdTask) error {
var data []interface{} var taskInfo TaskInfo
err := utils.JsonDecode(Text2ImgParamTemplate, &data) bytes, err := os.ReadFile(s.config.Txt2ImgJsonPath)
if err != nil { if err != nil {
return err return fmt.Errorf("error with load text2img json template file: %s", err.Error())
} }
err = json.Unmarshal(bytes, &taskInfo)
if err != nil {
return fmt.Errorf("error with decode json params: %s", err.Error())
}
data := taskInfo.Data
params := task.Params params := task.Params
data[ParamKeys["task_id"]] = params.TaskId data[ParamKeys["task_id"]] = params.TaskId
data[ParamKeys["prompt"]] = params.Prompt data[ParamKeys["prompt"]] = params.Prompt
@ -107,16 +116,12 @@ func (s *Service) Txt2Img(task types.SdTask) error {
data[ParamKeys["hd_scale_alg"]] = params.HdScaleAlg data[ParamKeys["hd_scale_alg"]] = params.HdScaleAlg
data[ParamKeys["hd_sample_num"]] = params.HdSteps data[ParamKeys["hd_sample_num"]] = params.HdSteps
taskInfo.SessionId = task.SessionId
taskInfo.TaskId = params.TaskId
taskInfo.Data = data
taskInfo.JobId = task.Id
go func() { go func() {
s.runTask(TaskInfo{ s.runTask(taskInfo, s.httpClient)
SessionId: task.SessionId,
JobId: task.Id,
TaskId: params.TaskId,
Data: data,
EventData: nil,
FnIndex: 232,
SessionHash: "ycaxgzm9ah",
}, s.httpClient)
}() }()
return nil return nil
} }
@ -177,9 +182,7 @@ func (s *Service) runTask(taskInfo TaskInfo, client *req.Client) {
return return
} }
//for k, v := range info { // 获取真实的 seed 值
// fmt.Println(k, " => ", v)
//}
cbReq.ImageName = images[0].Name cbReq.ImageName = images[0].Name
seed, _ := strconv.ParseInt(utils.InterfaceToString(info["seed"]), 10, 64) seed, _ := strconv.ParseInt(utils.InterfaceToString(info["seed"]), 10, 64)
cbReq.Seed = seed cbReq.Seed = seed
@ -278,7 +281,7 @@ func (s *Service) callback(data CBReq) {
return return
} }
if data.Progress < 100 { if data.Progress < 100 && data.ImageData != "" {
jobVo.ImgURL = data.ImageData jobVo.ImgURL = data.ImageData
} }
@ -295,7 +298,7 @@ func (s *Service) callback(data CBReq) {
utils.ReplyChunkMessage(client, vo.SdJob{ utils.ReplyChunkMessage(client, vo.SdJob{
Id: uint(data.JobId), Id: uint(data.JobId),
Progress: -1, Progress: -1,
Prompt: fmt.Sprintf("任务[%s]执行失败,已删除!", data.TaskId), TaskId: data.TaskId,
}) })
} }
} }

View File

@ -5,13 +5,13 @@ import logger2 "chatplus/logger"
var logger = logger2.GetLogger() var logger = logger2.GetLogger()
type TaskInfo struct { type TaskInfo struct {
SessionId string SessionId string `json:"session_id"`
JobId int JobId int `json:"job_id"`
TaskId string TaskId string `json:"task_id"`
Data []interface{} Data []interface{} `json:"data"`
EventData interface{} EventData interface{} `json:"event_data"`
FnIndex int FnIndex int `json:"fn_index"`
SessionHash string SessionHash string `json:"session_hash"`
} }
type CBReq struct { type CBReq struct {
@ -43,97 +43,3 @@ var ParamKeys = map[string]int{
"hd_scale_alg": 22, // 高清修复放大算法 "hd_scale_alg": 22, // 高清修复放大算法
"hd_sample_num": 23, // 高清修复采样次数 "hd_sample_num": 23, // 高清修复采样次数
} }
const Text2ImgParamTemplate = `[
"task(6sm0b3j17tag2gd)",
"A beautiful Chinese girl wearing a cheongsam walks on the bluestone street",
"",
[],
50,
"Euler a",
false,
false,
1,
1,
15,
null,
-1,
0,
0,
0,
false,
768,
512,
false,
0.7,
2,
"ESRGAN_4x",
10,
0,
0,
"Use same sampler",
"",
"",
[],
"None",
null,
false,
false,
"positive",
"comma",
0,
false,
false,
"",
"Seed",
"",
[],
"Nothing",
"",
[],
"Nothing",
"",
[],
true,
false,
false,
false,
0,
"Not set",
true,
true,
"",
"",
"",
"",
"",
1.3,
"Not set",
"Not set",
1.3,
"Not set",
1.3,
"Not set",
1.3,
1.3,
"Not set",
1.3,
"Not set",
1.3,
"Not set",
1.3,
"Not set",
1.3,
"Not set",
1.3,
"Not set",
false,
"None",
null,
false,
50,
[],
"",
"",
""
]`

View File

@ -2,16 +2,13 @@ package main
import ( import (
"fmt" "fmt"
"net/url" "os"
"path"
) )
func main() { func main() {
imgURL := "https://www.baidu.com/static/upload/2023/10/1696497571220711277.png?ex=6530f4a2&is=651e7fa28hmFd709d069ca05d7855ebdae42e5aa436883a36f9310d546" bytes, err := os.ReadFile("res/text2img.json")
parse, err := url.Parse(imgURL)
if err != nil { if err != nil {
panic(err) panic(err)
} }
fmt.Println(string(bytes))
fmt.Println(path.Ext(parse.Path))
} }

View File

@ -358,6 +358,7 @@ onMounted(() => {
httpGet("/api/admin/config/get?key=system").then(res => { httpGet("/api/admin/config/get?key=system").then(res => {
title.value = res.data.title title.value = res.data.title
rewardImg.value = res.data.reward_img
}).catch(e => { }).catch(e => {
ElMessage.error("获取系统配置失败:" + e.message) ElMessage.error("获取系统配置失败:" + e.message)
}) })

View File

@ -241,7 +241,7 @@
</div> </div>
<div class="param-line pt"> <div class="param-line pt">
<span>图片比例</span> <span>反向提示词</span>
<el-tooltip <el-tooltip
effect="light" effect="light"
content="不希望出现的元素,下面给了默认的起手式" content="不希望出现的元素,下面给了默认的起手式"
@ -486,12 +486,13 @@
import {onMounted, ref} from "vue" import {onMounted, ref} from "vue"
import {DocumentCopy, InfoFilled, Picture} from "@element-plus/icons-vue"; import {DocumentCopy, InfoFilled, Picture} from "@element-plus/icons-vue";
import {httpGet, httpPost} from "@/utils/http"; import {httpGet, httpPost} from "@/utils/http";
import {ElMessage} from "element-plus"; import {ElMessage, ElNotification} from "element-plus";
import ItemList from "@/components/ItemList.vue"; import ItemList from "@/components/ItemList.vue";
import Clipboard from "clipboard"; import Clipboard from "clipboard";
import {checkSession} from "@/action/session"; import {checkSession} from "@/action/session";
import {useRouter} from "vue-router"; import {useRouter} from "vue-router";
import {getSessionId, getUserToken} from "@/store/session"; import {getSessionId, getUserToken} from "@/store/session";
import {removeArrayItem} from "@/utils/libs";
const listBoxHeight = ref(window.innerHeight - 40) const listBoxHeight = ref(window.innerHeight - 40)
const mjBoxHeight = ref(window.innerHeight - 150) const mjBoxHeight = ref(window.innerHeight - 150)
@ -569,6 +570,14 @@ const connect = () => {
finishedJobs.value.unshift(data) finishedJobs.value.unshift(data)
} }
previewImgList.value.unshift(data["img_url"]) previewImgList.value.unshift(data["img_url"])
} else if (data.progress === -1) { //
ElNotification({
title: '任务执行失败',
message: "任务ID" + data['task_id'],
type: 'error',
})
runningJobs.value = removeArrayItem(runningJobs.value, data, (v1, v2) => v1.id === v2.id)
} else { // } else { //
for (let i = 0; i < runningJobs.value.length; i++) { for (let i = 0; i < runningJobs.value.length; i++) {
if (runningJobs.value[i].id === data.id) { if (runningJobs.value[i].id === data.id) {

View File

@ -24,6 +24,21 @@
<el-form-item label="开放AI绘画" prop="enabled_draw"> <el-form-item label="开放AI绘画" prop="enabled_draw">
<el-switch v-model="system['enabled_draw']"/> <el-switch v-model="system['enabled_draw']"/>
</el-form-item> </el-form-item>
<el-form-item label="收款二维码" prop="reward_img">
<el-input v-model="system['reward_img']" placeholder="众筹收款二维码地址">
<template #append>
<el-upload
:auto-upload="true"
:show-file-list="false"
:http-request="uploadRewardImg"
>
<el-icon class="uploader-icon">
<UploadFilled/>
</el-icon>
</el-upload>
</template>
</el-input>
</el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="save('system')">保存</el-button> <el-button type="primary" @click="save('system')">保存</el-button>
</el-form-item> </el-form-item>
@ -93,7 +108,9 @@
<script setup> <script setup>
import {onMounted, reactive, ref} from "vue"; import {onMounted, reactive, ref} from "vue";
import {httpGet, httpPost} from "@/utils/http"; import {httpGet, httpPost} from "@/utils/http";
import Compressor from "compressorjs";
import {ElMessage} from "element-plus"; import {ElMessage} from "element-plus";
import {UploadFilled} from "@element-plus/icons-vue";
const system = ref({models: []}) const system = ref({models: []})
const chat = ref({ const chat = ref({
@ -169,9 +186,30 @@ const save = function (key) {
} }
}) })
} }
} }
//
const uploadRewardImg = (file) => {
//
new Compressor(file.file, {
quality: 0.6,
success(result) {
const formData = new FormData();
formData.append('file', result, result.name);
//
httpPost('/api/upload', formData).then((res) => {
system.value['reward_img'] = res.data
ElMessage.success('上传成功')
}).catch((e) => {
ElMessage.error('上传失败:' + e.message)
})
},
error(err) {
console.log(err.message);
},
});
};
</script> </script>
<style lang="stylus" scoped> <style lang="stylus" scoped>
@ -195,6 +233,12 @@ const save = function (key) {
font-size 12px; font-size 12px;
line-height 1.5; line-height 1.5;
} }
.uploader-icon {
font-size 24px
position relative
top 3px
}
} }
} }