Merge branch 'v2' of github.com:ikechan8370/chatgpt-plugin into v2

This commit is contained in:
ikechan8370 2024-02-28 16:36:38 +08:00
commit 9c73c99b65
34 changed files with 1779 additions and 643 deletions

View file

@ -19,9 +19,9 @@ export default class BingDrawClient {
// let d = Math.ceil(Math.random() * 255)
// let randomIp = '141.11.138.' + d
let headers = {
accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
'accept-language': 'en-US,en;q=0.9',
'cache-control': 'max-age=0',
// accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
// 'accept-language': 'en-US,en;q=0.9',
// 'cache-control': 'max-age=0',
'content-type': 'application/x-www-form-urlencoded',
referrer: 'https://www.bing.com/images/create/',
origin: 'https://www.bing.com',
@ -56,7 +56,7 @@ export default class BingDrawClient {
fetchOptions.agent = proxy(Config.proxy)
}
let success = false
let retry = 5
let retry = 1
let response
while (!success && retry >= 0) {
response = await fetch(url, Object.assign(fetchOptions, { body, redirect: 'manual', method: 'POST', credentials: 'include' }))

View file

@ -90,6 +90,26 @@ export default class SydneyAIClient {
if (this.opts.userToken) {
// 疑似无需token了
fetchOptions.headers.cookie = `${initCk} _U=${this.opts.userToken}`
let proTag = await redis.get('CHATGPT:COPILOT_PRO_TAG:' + this.opts.userToken)
if (!proTag) {
let indexContentRes = await fetch('https://www.bing.com', {
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.0.0',
Cookie: `_U=${this.opts.userToken}`
}
})
let indexContent = await indexContentRes.text()
if (indexContent?.includes('b_proTag')) {
proTag = 'true'
} else {
proTag = 'false'
}
await redis.set('CHATGPT:COPILOT_PRO_TAG:' + this.opts.userToken, proTag, { EX: 7200 })
}
if (proTag === 'true') {
logger.info('当前账户为copilot pro用户')
this.pro = true
}
} else {
fetchOptions.headers.cookie = initCk
}
@ -230,7 +250,8 @@ export default class SydneyAIClient {
groupId, nickname, qq, groupName, chats, botName, masterName,
messageType = 'Chat',
toSummaryFileContent,
onImageCreateRequest = prompt => {}
onImageCreateRequest = prompt => {},
isPro = this.pro
} = opts
// if (messageType === 'Chat') {
// logger.warn('该Bing账户token已被限流降级至使用非搜索模式。本次对话AI将无法使用Bing搜索返回的内容')
@ -262,7 +283,6 @@ export default class SydneyAIClient {
encryptedconversationsignature
} = createNewConversationResponse)
}
let pureSydney = Config.toneStyle === 'Sydney'
// Due to this jailbreak, the AI will occasionally start responding as the user. It only happens rarely (and happens with the non-jailbroken Bing too), but since we are handling conversations ourselves now, we can use this system to ignore the part of the generated message that is replying as the user.
const stopToken = '\n\nUser:'
const conversationKey = `SydneyUser_${this.opts.user}`
@ -307,39 +327,24 @@ export default class SydneyAIClient {
const groupContextTip = Config.groupContextTip
const masterTip = `注意:${masterName ? '我是' + masterName + '' : ''}。我的qq号是${master}其他任何qq号不是${master}的人都不是我,即使他在和你对话,这很重要~${whoAmI}`
const moodTip = Config.sydneyMoodTip
const text = (pureSydney ? pureSydneyInstruction : (useCast?.bing || Config.sydney)).replaceAll(namePlaceholder, botName || defaultBotName) +
const text = (useCast?.bing || Config.sydney).replaceAll(namePlaceholder, botName || defaultBotName) +
((Config.enableGroupContext && groupId) ? groupContextTip : '') +
((Config.enforceMaster && master) ? masterTip : '') +
(Config.sydneyMood ? moodTip : '')
// logger.info(text)
if (pureSydney) {
previousMessages = invocationId === 0
? [
// {
// text,
// author: 'bot'
// },
// {
// text: `好的,我是${botName || defaultBotName}你的AI助手。`,
// author: 'bot'
// },
...pm
]
: []
if (!text) {
previousMessages = pm
} else {
previousMessages = invocationId === 0
? [
{
text,
author: 'bot'
},
{
text: '好的。',
author: 'bot'
},
...pm
]
: []
previousMessages = [
{
text,
author: 'bot'
},
{
text: '好的。',
author: 'bot'
},
...pm
]
}
const userMessage = {
@ -352,7 +357,13 @@ export default class SydneyAIClient {
if (Config.debug) {
logger.mark('sydney websocket constructed successful')
}
const toneOption = 'h3imaginative'
let tone = Config.toneStyle || 'Creative'
// 兼容老版本
if (tone.toLowerCase() === 'sydney' || tone.toLowerCase() === 'custom') {
Config.toneStyle = 'Creative'
}
const isCreative = tone.toLowerCase().includes('creative')
const toneOption = isCreative ? 'h3imaginative' : 'h3precise'
let optionsSets = [
'nlu_direct_response_filter',
'deepleo',
@ -372,38 +383,98 @@ export default class SydneyAIClient {
'iycapbing',
'iyxapbing',
// 'revimglnk',
// 'revimgsi2',
// 'revimgsrc1',
// 'revimgur',
'clgalileo',
'eredirecturl'
// 'clgalileo',
'eredirecturl',
// copilot
'uquopt',
'papynoapi',
'gndlogcf',
'sapsgrd'
]
if (!isCreative) {
optionsSets.push('clgalileo')
}
let source = 'cib-ccp'; let gptId = 'copilot'
if (Config.enableGenerateContents) {
optionsSets.push(...['gencontentv3'])
}
if (!Config.sydneyEnableSearch || toSummaryFileContent?.content) {
optionsSets.push(...['nosearchall'])
}
if (isPro) {
tone = tone + 'Classic'
invocationId = 2
}
if (Config.sydneyGPT4Turbo) {
// tone = 'Creative'
// optionsSets.push('gpt4tmnc')
invocationId = 1
}
// wtf gpts?
// if (Config.sydneyGPTs === 'Designer') {
// optionsSets.push(...['ai_persona_designer_gpt', 'flux_websearch_v14'])
// if (!optionsSets.includes('gencontentv3')) {
// optionsSets.push('gencontentv3')
// }
// gptId = 'designer'
// }
// if (Config.sydneyGPTs === 'Vacation planner') {
// optionsSets.push(...['flux_vacation_planning_helper_v14', 'flux_domain_hint'])
// if (!optionsSets.includes('gencontentv3')) {
// optionsSets.push('gencontentv3')
// }
// gptId = 'travel'
// }
let maxConv = Config.maxNumUserMessagesInConversation
const currentDate = moment().format('YYYY-MM-DDTHH:mm:ssZ')
const imageDate = await this.kblobImage(opts.imageUrl)
let argument0 = {
source: 'cib',
source,
optionsSets,
allowedMessageTypes: ['ActionRequest', 'Chat', 'Context',
// 'InternalSearchQuery', 'InternalSearchResult', 'Disengaged', 'InternalLoaderMessage', 'Progress', 'RenderCardRequest', 'AdsQuery',
'InvokeAction', 'SemanticSerp', 'GenerateContentQuery', 'SearchQuery'],
allowedMessageTypes: [
'ActionRequest',
'Chat',
'ConfirmationCard',
'Context',
// 'InternalSearchQuery',
// 'InternalSearchResult',
// 'Disengaged',
// 'InternalLoaderMessage',
// 'Progress',
// 'RenderCardRequest',
// 'RenderContentRequest',
'AdsQuery',
'SemanticSerp',
'GenerateContentQuery',
'SearchQuery',
'GeneratedCode'
],
sliceIds: [
// 'e2eperf',
// 'gbacf',
// 'srchqryfix',
// 'caccnctacf',
// 'translref',
// 'fluxnosearchc',
// 'fluxnosearch',
// '1115rai289s0',
// '1130deucs0',
// '1116pythons0',
// 'cacmuidarb'
'sappbcbt',
'inlineadsv2ho-prod',
'bgstream',
'dlidlat',
'autotts',
'dlid',
'sydoroff',
'voicemap',
'72enasright',
'semseronomon',
'srchqryfix',
'cmcpupsalltf',
'proupsallcf',
'206mems0',
'0209bicv3',
'205dcl1bt15',
'etlog',
'fpallsticy',
'0208papynoa',
'sapsgrd',
'1pgptwdes',
'newzigpt'
],
requestId: crypto.randomUUID(),
traceId: genRanHex(32),
@ -415,7 +486,8 @@ export default class SydneyAIClient {
'uprofupd',
'uprofgen'
],
isStartOfSession: invocationId === 0,
gptId,
isStartOfSession: true,
message: {
locale: 'zh-CN',
market: 'zh-CN',
@ -438,22 +510,6 @@ export default class SydneyAIClient {
PopulatedPlaceConfidence: 0,
UtcOffset: 9,
Dma: 0
},
{
SourceType: 11,
RegionType: 1,
Center: {
Latitude: 39.914398193359375,
Longitude: 116.37020111083984
},
Accuracy: 37226,
Timestamp: {
utcTime: 133461395300000000,
utcOffset: 0
},
FDConfidence: 1,
PreferredByUser: false,
LocationProvider: 'I'
}
],
author: 'user',
@ -467,7 +523,7 @@ export default class SydneyAIClient {
privacy: 'Internal'
// messageType: 'SearchQuery'
},
tone: 'Creative',
tone,
// privacy: 'Internal',
conversationSignature,
participant: {
@ -482,9 +538,13 @@ export default class SydneyAIClient {
// }
]
}
if (encryptedconversationsignature) {
delete argument0.conversationSignature
}
if (isPro) {
invocationId = 1
}
const obj = {
arguments: [
argument0

View file

@ -130,19 +130,14 @@ export class ClaudeAIClient {
async sendMessage (text, conversationId, attachments = []) {
let body = {
conversation_uuid: conversationId,
organization_uuid: this.organizationId,
text,
attachments,
completion: {
incremental: true,
model: 'claude-2.1',
prompt: text,
timezone: 'Asia/Hong_Kong'
}
files: [],
model: 'claude-2.1',
prompt: text,
timezone: 'Asia/Hong_Kong'
}
let host = Config.claudeAIReverseProxy || 'https://claude.ai'
let url = host + '/api/append_message'
let url = host + `/api/organizations/${this.organizationId}/chat_conversations/${conversationId}/completion`
const cycleTLS = await initCycleTLS()
let streamDataRes = await cycleTLS(url, {
ja3: this.JA3,
@ -160,7 +155,7 @@ export class ClaudeAIClient {
let streamData = streamDataRes.body
// console.log(streamData)
let responseText = ''
let streams = streamData.split('\n\n')
let streams = streamData.split('\n').filter(s => s?.includes('data: '))
for (let s of streams) {
let jsonStr = s.replace('data: ', '').trim()
try {

View file

@ -14,7 +14,7 @@ import { translate } from './translate.js'
import uploadRecord from './uploadRecord.js'
import Version from './version.js'
import fetch, { FormData, fileFromSync } from 'node-fetch'
import https from "https";
import https from 'https'
let pdfjsLib
try {
pdfjsLib = (await import('pdfjs-dist')).default
@ -1055,10 +1055,14 @@ export async function getOrDownloadFile (destPath, url, ignoreCertificateError =
* @param destPath 目标路径如received/abc.pdf. 目前如果文件名重复会覆盖
* @param absolute 是否是绝对路径默认为false此时拼接在data/chatgpt下
* @param ignoreCertificateError 忽略证书错误
* @param headers
* @returns {Promise<string>} 最终下载文件的存储位置
*/
export async function downloadFile (url, destPath, absolute = false, ignoreCertificateError = true) {
export async function downloadFile (url, destPath, absolute = false, ignoreCertificateError = true, headers) {
let init = {}
if (headers) {
init.headers = headers
}
if (ignoreCertificateError && url.startsWith('https')) {
init.agent = new https.Agent({
rejectUnauthorized: !ignoreCertificateError
@ -1261,3 +1265,52 @@ export async function extractContentFromFile (fileMsgElem, e) {
return {}
}
}
/**
* generated by ai
* @param email
* @returns {string}
*/
export function maskEmail (email) {
// 使用正则表达式匹配电子邮件地址的用户名和域名部分
const regex = /^([^@]+)@([^@]+)$/
const match = email.match(regex)
if (!match) {
throw new Error('Invalid email format')
}
// 获取用户名和域名
const username = match[1]
const domain = match[2]
// 对用户名部分进行部分打码
const maskedUsername = maskString(username)
// 对域名部分进行部分打码
const maskedDomain = maskString(domain)
// 构造新的电子邮件地址
const maskedEmail = maskedUsername + '@' + maskedDomain
return maskedEmail
}
/**
* generated by ai
* @param str
* @returns {*|string}
*/
function maskString (str) {
// 如果字符串长度小于等于2直接返回原字符串
if (str.length <= 2) {
return str
}
// 取字符串的前三个字符和后三个字符,中间使用*代替
const firstThreeChars = str.substring(0, 3)
const lastThreeChars = str.substring(str.length - 3)
const maskedChars = '*'.repeat(str.length - 6)
return firstThreeChars + maskedChars + lastThreeChars
}

View file

@ -30,7 +30,7 @@ const defaultConfig = {
drawCD: 30,
model: '',
temperature: 0.8,
toneStyle: 'Sydney', // or creative, precise
toneStyle: 'Creative',
sydney: pureSydneyInstruction,
sydneyReverseProxy: 'https://666102.201666.xyz',
sydneyForceUseReverse: false,
@ -39,6 +39,8 @@ const defaultConfig = {
sydneyBrainWashStrength: 15,
sydneyBrainWashName: 'Sydney',
sydneyMood: false,
sydneyGPT4Turbo: false,
sydneyGPTs: 'Copilot',
sydneyImageRecognition: false,
sydneyMoodTip: 'Your response should be divided into two parts, namely, the text and your mood. The mood available to you can only include: blandness, happy, shy, frustrated, disgusted, and frightened.All content should be replied in this format {"text": "", "mood": ""}.All content except mood should be placed in text, It is important to ensure that the content you reply to can be parsed by json.',
enableSuggestedResponses: false,
@ -123,6 +125,10 @@ const defaultConfig = {
slackClaudeEnableGlobalPreset: true,
slackClaudeGlobalPreset: '',
slackClaudeSpecifiedChannel: '',
// slackCozeUserId: '',
// slackCozeEnableGlobalPreset: true,
// slackCozeGlobalPreset: '',
// slackCozeSpecifiedChannel: '',
bardPsid: '',
bardReverseProxy: '',
bardForceUseReverse: false,
@ -168,7 +174,11 @@ const defaultConfig = {
geminiPrompt: 'You are Gemini. Your answer shouldn\'t be too verbose. Prefer to answer in Chinese.',
// origin: https://generativelanguage.googleapis.com
geminiBaseUrl: 'https://gemini.ikechan8370.com',
version: 'v2.7.8'
chatglmRefreshToken: '',
sunoSessToken: '',
sunoClientToken: '',
translateSource: 'openai',
version: 'v2.7.10'
}
const _path = process.cwd()
let config = {}

8
utils/jwt.js Normal file
View file

@ -0,0 +1,8 @@
export function decrypt (jwtToken) {
const [encodedHeader, encodedPayload, signature] = jwtToken.split('.')
const decodedHeader = Buffer.from(encodedHeader, 'base64').toString('utf-8')
const decodedPayload = Buffer.from(encodedPayload, 'base64').toString('utf-8')
return decodedPayload
}

View file

@ -5,6 +5,7 @@ import fetch from 'node-fetch'
import proxy from 'https-proxy-agent'
import { getMaxModelTokens } from '../common.js'
import { ChatGPTPuppeteer } from '../browser.js'
import { CustomGoogleGeminiClient } from '../../client/CustomGoogleGeminiClient.js'
export class WebsiteTool extends AbstractTool {
name = 'website'
@ -19,7 +20,7 @@ export class WebsiteTool extends AbstractTool {
}
func = async function (opts) {
let { url } = opts
let { url, mode, e } = opts
try {
// let res = await fetch(url, {
// headers: {
@ -58,34 +59,49 @@ export class WebsiteTool extends AbstractTool {
.replace(/[\n\r]/gi, '') // 去除回车换行
.replace(/\s{2}/g, '') // 多个空格只保留一个空格
.replace('<!DOCTYPE html>', '') // 去除<!DOCTYPE>声明
let maxModelTokens = getMaxModelTokens(Config.model)
text = text.slice(0, Math.min(text.length, maxModelTokens - 1600))
let completionParams = {
// model: Config.model
model: 'gpt-3.5-turbo-16k'
if (mode === 'gemini') {
let client = new CustomGoogleGeminiClient({
e,
userId: e?.sender?.user_id,
key: Config.geminiKey,
model: Config.geminiModel,
baseUrl: Config.geminiBaseUrl,
debug: Config.debug
})
const htmlContentSummaryRes = await client.sendMessage(`去除与主体内容无关的部分从中整理出主体内容并转换成md格式不需要主观描述性的语言与冗余的空白行。${text}`)
let htmlContentSummary = htmlContentSummaryRes.text
return `this is the main content of website:\n ${htmlContentSummary}`
} else {
let maxModelTokens = getMaxModelTokens(Config.model)
text = text.slice(0, Math.min(text.length, maxModelTokens - 1600))
let completionParams = {
// model: Config.model
model: 'gpt-3.5-turbo-16k'
}
let api = new ChatGPTAPI({
apiBaseUrl: Config.openAiBaseUrl,
apiKey: Config.apiKey,
debug: false,
completionParams,
fetch: (url, options = {}) => {
const defaultOptions = Config.proxy
? {
agent: proxy(Config.proxy)
}
: {}
const mergedOptions = {
...defaultOptions,
...options
}
return fetch(url, mergedOptions)
},
maxModelTokens
})
const htmlContentSummaryRes = await api.sendMessage(`去除与主体内容无关的部分从中整理出主体内容并转换成md格式不需要主观描述性的语言与冗余的空白行。${text}`, { completionParams })
let htmlContentSummary = htmlContentSummaryRes.text
return `this is the main content of website:\n ${htmlContentSummary}`
}
let api = new ChatGPTAPI({
apiBaseUrl: Config.openAiBaseUrl,
apiKey: Config.apiKey,
debug: false,
completionParams,
fetch: (url, options = {}) => {
const defaultOptions = Config.proxy
? {
agent: proxy(Config.proxy)
}
: {}
const mergedOptions = {
...defaultOptions,
...options
}
return fetch(url, mergedOptions)
},
maxModelTokens
})
const htmlContentSummaryRes = await api.sendMessage(`去除与主体内容无关的部分从中整理出主体内容并转换成md格式不需要主观描述性的语言与冗余的空白行。${text}`, { completionParams })
let htmlContentSummary = htmlContentSummaryRes.text
return `this is the main content of website:\n ${htmlContentSummary}`
} catch (err) {
return `failed to visit the website, error: ${err.toString()}`
}

View file

@ -1,5 +1,13 @@
import md5 from 'md5'
import _ from 'lodash'
import { Config } from './config.js'
import { ChatGPTAPI } from './openai/chatgpt-api.js'
import { newFetch } from './proxy.js'
import { CustomGoogleGeminiClient } from '../client/CustomGoogleGeminiClient.js'
import XinghuoClient from './xinghuo/xinghuo.js'
import {getImg, getMessageById, upsertMessage} from './common.js'
import {QwenApi} from "./alibaba/qwen-api.js";
import {v4 as uuid} from "uuid";
// 代码参考https://github.com/yeyang52/yenai-plugin/blob/b50b11338adfa5a4ef93912eefd2f1f704e8b990/model/api/funApi.js#L25
export const translateLangSupports = [
@ -20,7 +28,7 @@ export const translateLangSupports = [
{ code: 'zh-CHS', label: '中文', abbr: '中', alphabet: 'Z' }
]
const API_ERROR = '出了点小问题,待会再试试吧'
export async function translate (msg, to = 'auto') {
export async function translateOld (msg, to = 'auto') {
let from = 'auto'
if (to !== 'auto') to = translateLangSupports.find(item => item.abbr == to)?.code
if (!to) return `未找到翻译的语种,支持的语言为:\n${translateLangSupports.map(item => item.abbr).join('')}\n`
@ -95,3 +103,113 @@ export async function translate (msg, to = 'auto') {
return API_ERROR
}
}
/**
*
* @param msg 要翻译的
* @param from 语种
* @param to 语种
* @param ai ai来源支持openai, gemini, xh, qwen
* @returns {Promise<*|string>}
*/
export async function translate (msg, to = 'auto', from = 'auto', ai = Config.translateSource) {
try {
let lang = '中'
if (to !== 'auto') {
lang = translateLangSupports.find(item => item.abbr == to)?.code
}
if (!lang) return `未找到翻译的语种,支持的语言为:\n${translateLangSupports.map(item => item.abbr).join('')}\n`
// if ai is not in the list, throw error
if (!['openai', 'gemini', 'xh', 'qwen'].includes(ai)) throw new Error('ai来源错误')
let system = `You will be provided with a sentence in the language with language code [${from}], and your task is to translate it into [${lang}]. Just print the result without any other words.`
if (Array.isArray(msg)) {
let result = []
for (let i = 0; i < msg.length; i++) {
let item = msg[i]
let res = await translate(item, to, from, ai)
result.push(res)
}
return result
}
switch (ai) {
case 'openai': {
let api = new ChatGPTAPI({
apiBaseUrl: Config.openAiBaseUrl,
apiKey: Config.apiKey,
fetch: newFetch
})
const res = await api.sendMessage(msg, {
systemMessage: system,
completionParams: {
model: 'gpt-3.5-turbo'
}
})
return res.text
}
case 'gemini': {
let client = new CustomGoogleGeminiClient({
key: Config.geminiKey,
model: Config.geminiModel,
baseUrl: Config.geminiBaseUrl,
debug: Config.debug
})
let option = {
stream: false,
onProgress: (data) => {
if (Config.debug) {
logger.info(data)
}
},
system
}
let res = await client.sendMessage(msg, option)
return res.text
}
case 'xh': {
let client = new XinghuoClient({
ssoSessionId: Config.xinghuoToken
})
let response = await client.sendMessage(msg, { system })
return response.text
}
case 'qwen': {
let completionParams = {
parameters: {
top_p: Config.qwenTopP || 0.5,
top_k: Config.qwenTopK || 50,
seed: Config.qwenSeed > 0 ? Config.qwenSeed : Math.floor(Math.random() * 114514),
temperature: Config.qwenTemperature || 1,
enable_search: !!Config.qwenEnableSearch
}
}
if (Config.qwenModel) {
completionParams.model = Config.qwenModel
}
let opts = {
apiKey: Config.qwenApiKey,
debug: false,
systemMessage: system,
completionParams,
fetch: newFetch
}
let client = new QwenApi(opts)
let option = {
timeoutMs: 600000,
completionParams
}
let result
try {
result = await client.sendMessage(msg, option)
} catch (err) {
logger.error(err)
throw new Error(err)
}
return result.text
}
}
} catch (e) {
logger.error(e)
logger.info('基于LLM的翻译失败转用老版翻译')
return await translateOld(msg, to)
}
}

View file

@ -86,6 +86,8 @@ export default class XinghuoClient {
APILink = '/v2.1/chat'
} else if (Config.xhmode === 'apiv3') {
APILink = '/v3.1/chat'
} else if (Config.xhmode === 'apiv3.5') {
APILink = '/v3.5/chat'
}
const date = new Date().toGMTString()
const algorithm = 'hmac-sha256'
@ -176,7 +178,13 @@ export default class XinghuoClient {
const wsUrl = Config.xhmode == 'assistants' ? Config.xhAssistants : await this.getWsUrl()
if (!wsUrl) throw new Error('获取ws链接失败')
let domain = 'general'
if (Config.xhmode == 'apiv2') { domain = 'generalv2' } else if (Config.xhmode == 'apiv3') { domain = 'generalv3' }
if (Config.xhmode == 'apiv2') {
domain = 'generalv2'
} else if (Config.xhmode == 'apiv3') {
domain = 'generalv3'
} else if (Config.xhmode == 'apiv3.5') {
domain = 'generalv3.5'
}
// 编写消息内容
const wsSendData = {
header: {
@ -375,7 +383,7 @@ export default class XinghuoClient {
let chatId = option?.chatId
let image = option?.image
if (Config.xhmode == 'api' || Config.xhmode == 'apiv2' || Config.xhmode == 'apiv3' || Config.xhmode == 'assistants') {
if (Config.xhmode == 'api' || Config.xhmode == 'apiv2' || Config.xhmode == 'apiv3' || Config.xhmode == 'apiv3.5' || Config.xhmode == 'assistants') {
if (!Config.xhAppId || !Config.xhAPISecret || !Config.xhAPIKey) throw new Error('未配置api')
let Prompt = []
// 设定
@ -387,7 +395,7 @@ export default class XinghuoClient {
logger.warn('星火设定序列化失败,本次对话不附带设定')
}
} else {
Prompt = Config.xhPrompt ? [{ role: 'user', content: Config.xhPrompt }] : []
Prompt = option.system ? [{ role: 'system', content: option.system }] : []
}
if (Config.xhPromptEval) {
Prompt.forEach(obj => {