新功能: - 创建AI聊天助手组件(AIChatWidget) - 支持文字+图片多模态对话 - 集成Gemini AI API - 支持图片编辑和内容生成 - 实时对话历史管理 - 优雅的UI设计,支持黑夜模式 技术实现: - 后端API代理Gemini API(/api/ai-chat) - 支持最多5张图片上传 - 流式响应处理 - 对话历史管理 - Base64图片处理 配置: - 在.env中添加Gemini API配置 - GEMINI_API_KEY - GEMINI_API_BASE_URL - GEMINI_MODEL 替换原弹幕功能,提供更强大的AI助手体验!
180 lines
6.7 KiB
JavaScript
Executable File
180 lines
6.7 KiB
JavaScript
Executable File
const fs = require('fs');
|
||
const path = require('path');
|
||
|
||
// 读取server.js文件
|
||
const serverFilePath = path.join(__dirname, '..', 'server', 'server.js');
|
||
let content = fs.readFileSync(serverFilePath, 'utf8');
|
||
|
||
// 修复processSingleImage函数中的代码
|
||
const singleImageFunction = `
|
||
// 处理单张图片的辅助函数
|
||
async function processSingleImage(imageFile, prompt, model) {
|
||
console.log(\`处理单张图片 (\${imageFile.originalname}) 使用模型: \${model}\`);
|
||
|
||
// Select API Key based on model
|
||
let apiKey = '';
|
||
let apiUrl = ''; // API URL might also change based on model
|
||
let requestBody = {};
|
||
|
||
if (model === 'gemini-2.0-flash-exp-image-generation') {
|
||
apiKey = process.env.GEMINI_FLASH_API_KEY;
|
||
if (!apiKey) throw new Error('GEMINI_FLASH_API_KEY environment variable not set.');
|
||
apiUrl = 'https://api.zukedog.cn/v1/chat/completions';
|
||
// Construct Gemini request body
|
||
requestBody = {
|
||
model: model,
|
||
messages: [
|
||
{
|
||
role: "user",
|
||
content: [
|
||
{ type: "text", text: prompt },
|
||
{
|
||
type: "image_url",
|
||
image_url: {
|
||
url: \`data:\${imageFile.mimetype};base64,\${imageFile.buffer.toString('base64')}\`
|
||
}
|
||
}
|
||
]
|
||
}
|
||
],
|
||
max_tokens: 300
|
||
};
|
||
console.log('Using Gemini Flash API Key');
|
||
} else if (model === 'gpt-4o-image') {
|
||
apiKey = process.env.GPT4O_IMAGE_API_KEY;
|
||
if (!apiKey) throw new Error('GPT4O_IMAGE_API_KEY environment variable not set.');
|
||
apiUrl = 'https://api.zukedog.cn/v1/chat/completions';
|
||
// Construct GPT-4o request body
|
||
requestBody = {
|
||
model: model,
|
||
messages: [
|
||
{
|
||
role: "user",
|
||
content: [
|
||
{ type: "text", text: prompt },
|
||
{
|
||
type: "image_url",
|
||
image_url: {
|
||
url: \`data:\${imageFile.mimetype};base64,\${imageFile.buffer.toString('base64')}\`
|
||
}
|
||
}
|
||
]
|
||
}
|
||
],
|
||
max_tokens: 300
|
||
};
|
||
console.log('Using GPT-4o Image API Key');
|
||
} else {
|
||
throw new Error(\`Unsupported model selected: \${model}\`);
|
||
}
|
||
|
||
// API Call
|
||
console.log(\`调用API: \${apiUrl}\`);
|
||
try {
|
||
const response = await axios.post(apiUrl, requestBody, {
|
||
headers: {
|
||
'Authorization': \`Bearer \${apiKey}\`,
|
||
'Content-Type': 'application/json'
|
||
}
|
||
});
|
||
console.log('API调用成功');
|
||
return response.data;
|
||
} catch (error) {
|
||
console.error('API调用失败:', error.response ? error.response.data : error.message);
|
||
throw new Error(\`API call failed for model \${model}: \${error.message}\`);
|
||
}
|
||
}
|
||
`;
|
||
|
||
// 修复processMultipleImages函数中的代码
|
||
const multiImageFunction = `
|
||
// --- Process Multiple Images for Soul Assistant ---
|
||
// Modify this function to accept the model parameter and select the API key
|
||
async function processMultipleImages(imageFiles, prompt, model) {
|
||
console.log(\`处理多张图片 (\${imageFiles.length}张) 使用模型: \${model}\`);
|
||
|
||
// Select API Key based on model
|
||
let apiKey = '';
|
||
let apiUrl = ''; // API URL might also change based on model
|
||
let requestBody = {};
|
||
|
||
// Convert image files to base64 URLs for the request
|
||
const imageContent = imageFiles.map(file => ({
|
||
type: "image_url",
|
||
image_url: {
|
||
url: \`data:\${file.mimetype};base64,\${file.buffer.toString('base64')}\`
|
||
}
|
||
}));
|
||
|
||
if (model === 'gemini-2.0-flash-exp-image-generation') {
|
||
apiKey = process.env.GEMINI_FLASH_API_KEY;
|
||
if (!apiKey) throw new Error('GEMINI_FLASH_API_KEY environment variable not set.');
|
||
apiUrl = 'https://api.zukedog.cn/v1/chat/completions';
|
||
// Construct Gemini request body
|
||
requestBody = {
|
||
model: model,
|
||
messages: [
|
||
{
|
||
role: "user",
|
||
content: [
|
||
{ type: "text", text: prompt },
|
||
...imageContent // Spread the image objects into the content array
|
||
]
|
||
}
|
||
],
|
||
max_tokens: 300
|
||
};
|
||
console.log('Using Gemini Flash API Key');
|
||
} else if (model === 'gpt-4o-image') {
|
||
apiKey = process.env.GPT4O_IMAGE_API_KEY;
|
||
if (!apiKey) throw new Error('GPT4O_IMAGE_API_KEY environment variable not set.');
|
||
apiUrl = 'https://api.zukedog.cn/v1/chat/completions';
|
||
// Construct GPT-4o request body
|
||
requestBody = {
|
||
model: model,
|
||
messages: [
|
||
{
|
||
role: "user",
|
||
content: [
|
||
{ type: "text", text: prompt },
|
||
...imageContent // Spread the image objects into the content array
|
||
]
|
||
}
|
||
],
|
||
max_tokens: 300
|
||
};
|
||
console.log('Using GPT-4o Image API Key');
|
||
} else {
|
||
throw new Error(\`Unsupported model selected: \${model}\`);
|
||
}
|
||
|
||
// API Call
|
||
console.log(\`调用API: \${apiUrl}\`);
|
||
try {
|
||
const response = await axios.post(apiUrl, requestBody, {
|
||
headers: {
|
||
'Authorization': \`Bearer \${apiKey}\`,
|
||
'Content-Type': 'application/json'
|
||
}
|
||
});
|
||
console.log('API调用成功');
|
||
return response.data;
|
||
} catch (error) {
|
||
console.error('API调用失败:', error.response ? error.response.data : error.message);
|
||
throw new Error(\`API call failed for model \${model}: \${error.message}\`);
|
||
}
|
||
}
|
||
`;
|
||
|
||
// 替换整个processSingleImage函数
|
||
const singleImageRegex = /\/\/ 处理单张图片的辅助函数[\s\S]*?\/\/ --- End Example API Call ---\n}/;
|
||
content = content.replace(singleImageRegex, singleImageFunction);
|
||
|
||
// 替换整个processMultipleImages函数
|
||
const multiImageRegex = /\/\/ --- Process Multiple Images for Soul Assistant ---[\s\S]*?\/\/ --- End Example API Call ---\n}/;
|
||
content = content.replace(multiImageRegex, multiImageFunction);
|
||
|
||
// 写回文件
|
||
fs.writeFileSync(serverFilePath, content, 'utf8');
|
||
|
||
console.log('API配置已成功修复!两个函数都已更新为使用 https://api.zukedog.cn/v1/chat/completions API地址,并使用了OpenAI兼容的请求格式!');
|