mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-09-22 06:00:56 +02:00

* WIP: initial logging changes add several transports in ~/config/winston omit messages in logs, truncate long strings add short blurb in dotenv for debug logging GoogleClient: using logger OpenAIClient: using logger, handleOpenAIErrors Adding typedef for payload message bumped winston and using winston-daily-rotate-file moved config for server paths to ~/config dir Added `DEBUG_LOGGING=true` to .env.example * WIP: Refactor logging statements in code * WIP: Refactor logging statements and import configurations * WIP: Refactor logging statements and import configurations * refactor: broadcast Redis initialization message with `info` not `debug` * refactor: complete Refactor logging statements and import configurations * chore: delete unused tools * fix: circular dependencies due to accessing logger * refactor(handleText): handle booleans and write tests * refactor: redact sensitive values, better formatting * chore: improve log formatting, avoid passing strings to 2nd arg * fix(ci): fix jest tests due to logger changes * refactor(getAvailablePluginsController): cache plugins as they are static and avoids async addOpenAPISpecs call every time * chore: update docs * chore: update docs * chore: create separate meiliSync logger, clean up logs to avoid being unnecessarily verbose * chore: spread objects where they are commonly logged to allow string truncation * chore: improve error log formatting
93 lines
3.5 KiB
JavaScript
93 lines
3.5 KiB
JavaScript
// Generates image using stable diffusion webui's api (automatic1111)
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const axios = require('axios');
|
|
const sharp = require('sharp');
|
|
const { Tool } = require('langchain/tools');
|
|
const { logger } = require('~/config');
|
|
|
|
class StableDiffusionAPI extends Tool {
|
|
constructor(fields) {
|
|
super();
|
|
this.name = 'stable-diffusion';
|
|
this.url = fields.SD_WEBUI_URL || this.getServerURL();
|
|
this.description = `You can generate images with 'stable-diffusion'. This tool is exclusively for visual content.
|
|
Guidelines:
|
|
- Visually describe the moods, details, structures, styles, and/or proportions of the image. Remember, the focus is on visual attributes.
|
|
- Craft your input by "showing" and not "telling" the imagery. Think in terms of what you'd want to see in a photograph or a painting.
|
|
- It's best to follow this format for image creation:
|
|
"detailed keywords to describe the subject, separated by comma | keywords we want to exclude from the final image"
|
|
- Here's an example prompt for generating a realistic portrait photo of a man:
|
|
"photo of a man in black clothes, half body, high detailed skin, coastline, overcast weather, wind, waves, 8k uhd, dslr, soft lighting, high quality, film grain, Fujifilm XT3 | semi-realistic, cgi, 3d, render, sketch, cartoon, drawing, anime, out of frame, low quality, ugly, mutation, deformed"
|
|
- Generate images only once per human query unless explicitly requested by the user`;
|
|
}
|
|
|
|
replaceNewLinesWithSpaces(inputString) {
|
|
return inputString.replace(/\r\n|\r|\n/g, ' ');
|
|
}
|
|
|
|
getMarkdownImageUrl(imageName) {
|
|
const imageUrl = path
|
|
.join(this.relativeImageUrl, imageName)
|
|
.replace(/\\/g, '/')
|
|
.replace('public/', '');
|
|
return ``;
|
|
}
|
|
|
|
getServerURL() {
|
|
const url = process.env.SD_WEBUI_URL || '';
|
|
if (!url) {
|
|
throw new Error('Missing SD_WEBUI_URL environment variable.');
|
|
}
|
|
return url;
|
|
}
|
|
|
|
async _call(input) {
|
|
const url = this.url;
|
|
const payload = {
|
|
prompt: input.split('|')[0],
|
|
negative_prompt: input.split('|')[1],
|
|
sampler_index: 'DPM++ 2M Karras',
|
|
cfg_scale: 4.5,
|
|
steps: 22,
|
|
width: 1024,
|
|
height: 1024,
|
|
};
|
|
const response = await axios.post(`${url}/sdapi/v1/txt2img`, payload);
|
|
const image = response.data.images[0];
|
|
|
|
const pngPayload = { image: `data:image/png;base64,${image}` };
|
|
const response2 = await axios.post(`${url}/sdapi/v1/png-info`, pngPayload);
|
|
const info = response2.data.info;
|
|
|
|
// Generate unique name
|
|
const imageName = `${Date.now()}.png`;
|
|
this.outputPath = path.resolve(__dirname, '..', '..', '..', '..', 'client', 'public', 'images');
|
|
const appRoot = path.resolve(__dirname, '..', '..', '..', '..', 'client');
|
|
this.relativeImageUrl = path.relative(appRoot, this.outputPath);
|
|
|
|
// Check if directory exists, if not create it
|
|
if (!fs.existsSync(this.outputPath)) {
|
|
fs.mkdirSync(this.outputPath, { recursive: true });
|
|
}
|
|
|
|
try {
|
|
const buffer = Buffer.from(image.split(',', 1)[0], 'base64');
|
|
await sharp(buffer)
|
|
.withMetadata({
|
|
iptcpng: {
|
|
parameters: info,
|
|
},
|
|
})
|
|
.toFile(this.outputPath + '/' + imageName);
|
|
this.result = this.getMarkdownImageUrl(imageName);
|
|
} catch (error) {
|
|
logger.error('[StableDiffusion] Error while saving the image:', error);
|
|
// this.result = theImageUrl;
|
|
}
|
|
|
|
return this.result;
|
|
}
|
|
}
|
|
|
|
module.exports = StableDiffusionAPI;
|