mirror of
https://github.com/ikechan8370/chatgpt-plugin.git
synced 2025-12-16 13:27:08 +00:00
修改suno伪造生成策略,支持更多模型调用
This commit is contained in:
parent
123e5304a7
commit
d111d2625e
7 changed files with 86 additions and 30 deletions
29
apps/chat.js
29
apps/chat.js
|
|
@ -5,6 +5,7 @@ import { Config } from '../utils/config.js'
|
|||
import { v4 as uuid } from 'uuid'
|
||||
import AzureTTS from '../utils/tts/microsoft-azure.js'
|
||||
import VoiceVoxTTS from '../utils/tts/voicevox.js'
|
||||
import BingSunoClient from '../utils/BingSuno.js'
|
||||
import {
|
||||
completeJSON,
|
||||
formatDate,
|
||||
|
|
@ -20,7 +21,8 @@ import {
|
|||
makeForwardMsg,
|
||||
randomString,
|
||||
render,
|
||||
renderUrl
|
||||
renderUrl,
|
||||
extractMarkdownJson
|
||||
} from '../utils/common.js'
|
||||
|
||||
import fetch from 'node-fetch'
|
||||
|
|
@ -838,6 +840,31 @@ export class chatgpt extends plugin {
|
|||
await redis.set(key, JSON.stringify(previousConversation), Config.conversationPreserveTime > 0 ? { EX: Config.conversationPreserveTime } : {})
|
||||
}
|
||||
}
|
||||
// 处理suno生成
|
||||
if ((use === 'bing' || use === 'xh') && Config.enableChatSuno) {
|
||||
const sunoList = extractMarkdownJson(chatMessage.text)
|
||||
for (let suno of sunoList) {
|
||||
if (suno.json.option == 'Suno') {
|
||||
chatMessage.text = chatMessage.text.replace(suno.markdown, `歌曲 《${suno.json.title}》`)
|
||||
logger.info(`开始生成歌曲${suno.json.tags}`)
|
||||
let client = new BingSunoClient() // 此处使用了bing的suno客户端,后续和本地suno合并
|
||||
redis.set(`CHATGPT:SUNO:${e.sender.user_id}`, 'c', { EX: 30 }).then(() => {
|
||||
try {
|
||||
if (Config.SunoModel == 'local') {
|
||||
// 调用本地Suno配置进行歌曲生成
|
||||
client.getLocalSuno(suno.json, e)
|
||||
} else if (Config.SunoModel == 'api') {
|
||||
// 调用第三方Suno配置进行歌曲生成
|
||||
client.getApiSuno(suno.json, e)
|
||||
}
|
||||
} catch (err) {
|
||||
redis.del(`CHATGPT:SUNO:${e.sender.user_id}`)
|
||||
this.reply('歌曲生成失败:' + err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
let response = chatMessage?.text?.replace('\n\n\n', '\n')
|
||||
let mood = 'blandness'
|
||||
if (!response) {
|
||||
|
|
|
|||
|
|
@ -580,11 +580,6 @@
|
|||
"label": "允许生成歌曲等内容",
|
||||
"data": "enableGenerateSuno"
|
||||
},
|
||||
{
|
||||
"type": "check",
|
||||
"label": "伪造歌曲生成",
|
||||
"data": "enableGenerateSunoForger"
|
||||
},
|
||||
{
|
||||
"type": "url",
|
||||
"label": "必应验证码pass服务",
|
||||
|
|
@ -603,12 +598,6 @@
|
|||
"data": "bingSuno",
|
||||
"items": [ { "label": "Bing", "value": "bing" }, { "label": "本地", "value": "local" }, { "label": "第三方", "value": "api" } ]
|
||||
},
|
||||
{
|
||||
"type": "url",
|
||||
"label": "第三方歌曲生成API地址",
|
||||
"placeholder": "https://github.com/gcui-art/suno-api的api地址",
|
||||
"data": "bingSunoApi"
|
||||
},
|
||||
{
|
||||
"type": "textarea",
|
||||
"label": "前置对话第一轮(用户)",
|
||||
|
|
@ -1054,6 +1043,23 @@
|
|||
"label": "client token",
|
||||
"placeholder": "suno的__client token,需要与sunoSessToken一一对应数量相同,多个用逗号隔开",
|
||||
"data": "sunoClientToken"
|
||||
},
|
||||
{
|
||||
"type": "check",
|
||||
"label": "允许聊天指令声音音乐",
|
||||
"data": "enableChatSuno"
|
||||
},
|
||||
{
|
||||
"type": "select",
|
||||
"label": "调用模式",
|
||||
"data": "SunoModel",
|
||||
"items": [ { "label": "本地", "value": "local" }, { "label": "第三方", "value": "api" } ]
|
||||
},
|
||||
{
|
||||
"type": "url",
|
||||
"label": "第三方歌曲生成API地址",
|
||||
"placeholder": "https://github.com/gcui-art/suno-api的api地址",
|
||||
"data": "bingSunoApi"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
|||
|
|
@ -69,10 +69,10 @@ export default class BingSunoClient {
|
|||
sunoURL,
|
||||
prompt: prompt.songPrompt
|
||||
}
|
||||
await e.reply('Bing Suno 生成中,请稍后')
|
||||
await e.reply('Suno 生成中,请稍后')
|
||||
this.replyMsg(sunoDisplayResult, e)
|
||||
} else {
|
||||
await e.reply('Bing Suno 数据获取失败')
|
||||
await e.reply('Suno 数据获取失败')
|
||||
redis.del(`CHATGPT:SUNO:${e.sender.user_id}`)
|
||||
}
|
||||
redis.del(`CHATGPT:SUNO:${e.sender.user_id}`)
|
||||
|
|
@ -84,7 +84,7 @@ export default class BingSunoClient {
|
|||
redis.del(`CHATGPT:SUNO:${e.sender.user_id}`)
|
||||
return true
|
||||
}
|
||||
let description = prompt.songPrompt
|
||||
let description = prompt.songPrompt || prompt.lyrics
|
||||
await e.reply('正在生成,请稍后')
|
||||
try {
|
||||
let sessTokens = Config.sunoSessToken.split(',')
|
||||
|
|
|
|||
|
|
@ -338,7 +338,7 @@ export default class SydneyAIClient {
|
|||
((Config.enableGroupContext && groupId) ? groupContextTip : '') +
|
||||
((Config.enforceMaster && master) ? masterTip : '') +
|
||||
(Config.sydneyMood ? moodTip : '') +
|
||||
((!Config.enableGenerateSuno && Config.bingSuno != 'bing' && Config.enableGenerateSunoForger) ? 'If I ask you to generate music or write songs, you need to reply with information suitable for Suno to generate music. Please use keywords such as Verse, Chorus, Bridge, Outro, and End to segment the lyrics, such as [Verse], The returned message is in JSON format, with a structure of {"option": "Suno", "tags": "style", "title": "title of the song", "lyrics": "lyrics"}.' : '')
|
||||
((!Config.enableGenerateSuno && Config.enableChatSuno) ? 'If I ask you to generate music or write songs, you need to reply with information suitable for Suno to generate music. Please use keywords such as Verse, Chorus, Bridge, Outro, and End to segment the lyrics, such as [Verse], The returned message is in JSON format, with a structure of {"option": "Suno", "tags": "style", "title": "title of the song", "lyrics": "lyrics"}.' : '')
|
||||
if (!text) {
|
||||
previousMessages = pm
|
||||
} else {
|
||||
|
|
@ -835,17 +835,6 @@ export default class SydneyAIClient {
|
|||
message.adaptiveCards = adaptiveCardsSoFar
|
||||
message.text = replySoFar.join('')
|
||||
}
|
||||
// 伪造歌曲生成
|
||||
if (Config.enableGenerateSunoForger) {
|
||||
const sunoList = extractMarkdownJson(message.text)
|
||||
for (let suno of sunoList) {
|
||||
if (suno.json.option == 'Suno') {
|
||||
message.text = message.text.replace(suno.markdown, `歌曲 《${suno.json.title}》`)
|
||||
logger.info(`开始生成歌曲${suno.json.tags}`)
|
||||
onSunoCreateRequest(suno.json)
|
||||
}
|
||||
}
|
||||
}
|
||||
resolve({
|
||||
message,
|
||||
conversationExpiryTime: event?.item?.conversationExpiryTime
|
||||
|
|
|
|||
|
|
@ -1243,6 +1243,34 @@ function maskString (str) {
|
|||
return firstThreeChars + maskedChars + lastThreeChars
|
||||
}
|
||||
|
||||
/**
|
||||
* generated by ai
|
||||
* @param rawJsonString
|
||||
* @returns {string}
|
||||
*/
|
||||
function fixNewlinesInJsonString(rawJsonString) {
|
||||
// 标记是否在字符串内
|
||||
let inString = false
|
||||
// 结果字符串
|
||||
let result = ''
|
||||
for (let i = 0; i < rawJsonString.length; i++) {
|
||||
const currentChar = rawJsonString[i]
|
||||
const nextChar = i + 1 < rawJsonString.length ? rawJsonString[i + 1] : ''
|
||||
// 检查当前字符是否为双引号,且不是转义的双引号
|
||||
if (currentChar === '"' && (i === 0 || rawJsonString[i - 1] !== '\\')) {
|
||||
inString = !inString // 切换在字符串内的标记
|
||||
}
|
||||
// 如果在字符串内且遇到换行符,则替换为\\n
|
||||
if (inString && (currentChar === '\n' || (currentChar === '\r' && nextChar === '\n'))) {
|
||||
result += '\\n'
|
||||
if (currentChar === '\r') i++ // 跳过\n
|
||||
} else {
|
||||
result += currentChar
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* generated by ai
|
||||
* @param text
|
||||
|
|
@ -1259,7 +1287,7 @@ export function extractMarkdownJson(text) {
|
|||
// 如果已经在一个 JSON 中,先结束当前的 JSON
|
||||
if (currentJson) {
|
||||
try {
|
||||
const parsedJson = JSON.parse(currentJson)
|
||||
const parsedJson = JSON.parse(fixNewlinesInJsonString(currentJson))
|
||||
mdJsonPairs.push({ json: parsedJson, markdown: currentMd + '```' })
|
||||
} catch (e) {
|
||||
console.error('JSON解析错误:', e)
|
||||
|
|
@ -1271,7 +1299,7 @@ export function extractMarkdownJson(text) {
|
|||
} else if (line.startsWith('```') && currentJson) {
|
||||
// 结束当前的 JSON
|
||||
try {
|
||||
const parsedJson = JSON.parse(currentJson)
|
||||
const parsedJson = JSON.parse(fixNewlinesInJsonString(currentJson))
|
||||
mdJsonPairs.push({ json: parsedJson, markdown: currentMd + line })
|
||||
} catch (e) {
|
||||
console.error('JSON解析错误:', e)
|
||||
|
|
|
|||
|
|
@ -154,7 +154,6 @@ const defaultConfig = {
|
|||
autoJapanese: false,
|
||||
enableGenerateContents: false,
|
||||
enableGenerateSuno: false,
|
||||
enableGenerateSunoForger: false,
|
||||
amapKey: '',
|
||||
azSerpKey: '',
|
||||
serpSource: 'ikechan8370',
|
||||
|
|
@ -186,6 +185,8 @@ const defaultConfig = {
|
|||
chatglmRefreshToken: '',
|
||||
sunoSessToken: '',
|
||||
sunoClientToken: '',
|
||||
enableChatSuno: false,
|
||||
SunoModel: 'local',
|
||||
|
||||
claudeApiKey: '',
|
||||
claudeApiBaseUrl: 'http://claude-api.ikechan8370.com',
|
||||
|
|
|
|||
|
|
@ -397,6 +397,11 @@ export default class XinghuoClient {
|
|||
} else {
|
||||
Prompt = option.system ? [{ role: 'system', content: option.system }] : []
|
||||
}
|
||||
if (Config.enableChatSuno) {
|
||||
Prompt.unshift(
|
||||
{ role: 'system', content: '如果我要求你生成音乐或写歌,你需要回复适合Suno生成音乐的信息。请使用Verse、Chorus、Bridge、Outro和End等关键字对歌词进行分段,如[Verse]。返回的消息需要使用markdown包裹的JSON格式,结构为```json{"option": "Suno", "tags": "style", "title": "title of the song", "lyrics": "lyrics"}```。' }
|
||||
)
|
||||
}
|
||||
if (Config.xhPromptEval) {
|
||||
Prompt.forEach(obj => {
|
||||
try {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue