fix (templates): ai-search OK. Image by AI.
This commit is contained in:
parent
22fcf8b541
commit
1bae1ed5e9
9 changed files with 127 additions and 97 deletions
|
@ -39,6 +39,9 @@ import urlJoin from 'url-join';
|
||||||
import { GBServer } from '../../../src/app.js';
|
import { GBServer } from '../../../src/app.js';
|
||||||
import { GBLogEx } from '../../core.gbapp/services/GBLogEx.js';
|
import { GBLogEx } from '../../core.gbapp/services/GBLogEx.js';
|
||||||
import { GBUtil } from '../../../src/util.js';
|
import { GBUtil } from '../../../src/util.js';
|
||||||
|
import fs from 'fs/promises';
|
||||||
|
import { AzureOpenAI } from 'openai';
|
||||||
|
import { OpenAIClient } from '@langchain/openai';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Image processing services of conversation to be called by BASIC.
|
* Image processing services of conversation to be called by BASIC.
|
||||||
|
@ -64,8 +67,7 @@ export class ImageProcessingServices {
|
||||||
*
|
*
|
||||||
* file = MERGE file1, file2, file3
|
* file = MERGE file1, file2, file3
|
||||||
*/
|
*/
|
||||||
public async mergeImage({pid, files})
|
public async mergeImage({ pid, files }) {
|
||||||
{
|
|
||||||
const { min, user } = await DialogKeywords.getProcessInfo(pid);
|
const { min, user } = await DialogKeywords.getProcessInfo(pid);
|
||||||
|
|
||||||
let paths = [];
|
let paths = [];
|
||||||
|
@ -77,12 +79,16 @@ export class ImageProcessingServices {
|
||||||
const botId = min.instance.botId;
|
const botId = min.instance.botId;
|
||||||
const packagePath = GBUtil.getGBAIPath(min.botId);
|
const packagePath = GBUtil.getGBAIPath(min.botId);
|
||||||
// TODO: const img = await joinImages(paths);
|
// TODO: const img = await joinImages(paths);
|
||||||
const localName = path.join('work', packagePath, 'cache', `img-mrg${GBAdminService.getRndReadableIdentifier()}.png`);
|
const localName = path.join(
|
||||||
|
'work',
|
||||||
|
packagePath,
|
||||||
|
'cache',
|
||||||
|
`img-mrg${GBAdminService.getRndReadableIdentifier()}.png`
|
||||||
|
);
|
||||||
const url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(localName));
|
const url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', path.basename(localName));
|
||||||
// img.toFile(localName);
|
// img.toFile(localName);
|
||||||
|
|
||||||
return { localName: localName, url: url, data: null };
|
return { localName: localName, url: url, data: null };
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -98,4 +104,75 @@ export class ImageProcessingServices {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async getImageFromPrompt({ pid, prompt }) {
|
||||||
|
const { min, user, params } = await DialogKeywords.getProcessInfo(pid);
|
||||||
|
|
||||||
|
const azureOpenAIKey = await min.core.getParam(min.instance, 'Azure Open AI Key', null, true);
|
||||||
|
const azureOpenAIEndpoint = await min.core.getParam(min.instance, 'Azure Open AI Endpoint', null, true);
|
||||||
|
const azureOpenAIVersion = await (min.core as any)['getParam'](min.instance, 'Azure Open AI Version', null, true);
|
||||||
|
const azureOpenAIImageModel = await (min.core as any)['getParam'](min.instance, 'Azure Open AI Image Model', null, true);
|
||||||
|
|
||||||
|
|
||||||
|
if (azureOpenAIKey) {
|
||||||
|
// Initialize the Azure OpenAI client
|
||||||
|
|
||||||
|
const client = new AzureOpenAI({
|
||||||
|
baseURL: azureOpenAIEndpoint,
|
||||||
|
apiVersion: azureOpenAIVersion,
|
||||||
|
apiKey: azureOpenAIKey
|
||||||
|
});
|
||||||
|
|
||||||
|
// Make a request to the image generation endpoint
|
||||||
|
|
||||||
|
const response = await client.images.generate({
|
||||||
|
model: azureOpenAIImageModel,
|
||||||
|
prompt: prompt,
|
||||||
|
n: 1,
|
||||||
|
size: '1024x1024'
|
||||||
|
});
|
||||||
|
|
||||||
|
const gbaiName = GBUtil.getGBAIPath(min.botId);
|
||||||
|
const localName = path.join('work', gbaiName, 'cache', `DALL-E${GBAdminService.getRndReadableIdentifier()}.png`);
|
||||||
|
|
||||||
|
const url = response.data[0].url;
|
||||||
|
const res = await fetch(url);
|
||||||
|
let buf: any = Buffer.from(await res.arrayBuffer());
|
||||||
|
await fs.writeFile(localName, buf, { encoding: null });
|
||||||
|
|
||||||
|
GBLogEx.info(min, `DALL-E: ${url} - ${response.data[0].revised_prompt}.`);
|
||||||
|
|
||||||
|
return { localName, url };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getCaptionForImage({ pid, imageUrl }) {
|
||||||
|
const { min, user, params } = await DialogKeywords.getProcessInfo(pid);
|
||||||
|
|
||||||
|
const azureOpenAIKey = await min.core.getParam(min.instance, 'Azure Open AI Key', null);
|
||||||
|
const azureOpenAITextModel = 'gpt-4'; // Specify GPT-4 model here
|
||||||
|
const azureOpenAIEndpoint = await min.core.getParam(min.instance, 'Azure Open AI Endpoint', null);
|
||||||
|
const azureOpenAIVersion = await (min.core as any)['getParam'](min.instance, 'Azure Open AI Version', null, true);
|
||||||
|
|
||||||
|
if (azureOpenAIKey && azureOpenAITextModel && imageUrl) {
|
||||||
|
const client = new AzureOpenAI({
|
||||||
|
apiVersion: azureOpenAIVersion,
|
||||||
|
apiKey: azureOpenAIKey,
|
||||||
|
baseURL: azureOpenAIEndpoint
|
||||||
|
});
|
||||||
|
|
||||||
|
const prompt = `Provide a descriptive caption for the image at the following URL: ${imageUrl}`;
|
||||||
|
|
||||||
|
const response = await client.completions.create({
|
||||||
|
|
||||||
|
model: azureOpenAITextModel,
|
||||||
|
prompt: prompt,
|
||||||
|
max_tokens: 50
|
||||||
|
});
|
||||||
|
|
||||||
|
const caption = response['data'].choices[0].text.trim();
|
||||||
|
GBLogEx.info(min, `Generated caption: ${caption}`);
|
||||||
|
|
||||||
|
return { caption };
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -484,11 +484,20 @@ export class KeywordsExpressions {
|
||||||
keywords[i++] = [
|
keywords[i++] = [
|
||||||
/^\s*(.*)\=\s*(GET IMAGE)(\s*)(.*)/gim,
|
/^\s*(.*)\=\s*(GET IMAGE)(\s*)(.*)/gim,
|
||||||
($0, $1, $2, $3, $4) => {
|
($0, $1, $2, $3, $4) => {
|
||||||
const params = this.getParams($4, ['text']);
|
const params = this.getParams($4, ['prompt']);
|
||||||
return `${$1} = await img.getImageFromPrompt({pid: pid, ${params}})`;
|
return `${$1} = await img.getImageFromPrompt({pid: pid, ${params}})`;
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
keywords[i++] = [
|
||||||
|
/\s*(PLAY)(\s*)(.*)/gim,
|
||||||
|
($0, $1, $2, $3, $4) => {
|
||||||
|
const params = this.getParams($3, ['file']);
|
||||||
|
return `await sys.play({pid: pid, ${params}})`;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
keywords[i++] = [
|
keywords[i++] = [
|
||||||
/^\s*(.*)\=\s*(AUTO SAVE)(\s*)(.*)/gim,
|
/^\s*(.*)\=\s*(AUTO SAVE)(\s*)(.*)/gim,
|
||||||
($0, $1, $2, $3, $4) => {
|
($0, $1, $2, $3, $4) => {
|
||||||
|
|
|
@ -2822,7 +2822,7 @@ export class SystemKeywords {
|
||||||
async bail => {
|
async bail => {
|
||||||
if (table.endsWith('.csv')) {
|
if (table.endsWith('.csv')) {
|
||||||
// CSV handling
|
// CSV handling
|
||||||
const packagePath = GBUtil.getGBAIPath(min.botId, "gbdata");
|
const packagePath = GBUtil.getGBAIPath(min.botId, 'gbdata');
|
||||||
const csvFile = path.join(GBConfigService.get('STORAGE_LIBRARY'), packagePath, `${table}`);
|
const csvFile = path.join(GBConfigService.get('STORAGE_LIBRARY'), packagePath, `${table}`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -2860,4 +2860,12 @@ export class SystemKeywords {
|
||||||
);
|
);
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async play({ pid, file }) {
|
||||||
|
const { min, user, params, step } = await DialogKeywords.getProcessInfo(pid);
|
||||||
|
|
||||||
|
await min.kbService.playUrl(min, min.conversationalService, step, file?.url ? file.url : file);
|
||||||
|
|
||||||
|
await this.setMemoryContext({ pid, erase: true });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,13 +58,14 @@
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Focus the input field after rendering
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const input = document.querySelector('.webchat__send-box-text-box__input');
|
const input = document.querySelector('.webchat__send-box-text-box__input');
|
||||||
if (input) {
|
if (input) {
|
||||||
input.focus();
|
input.focus();
|
||||||
}
|
}
|
||||||
}, 3000); // Adjust timing as needed
|
}, 3000); // Adjust timing as needed
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
|
|
@ -1383,7 +1383,7 @@ export class KBService implements IGBKBService {
|
||||||
conversationalService.sendAudio(min, step, answer.content);
|
conversationalService.sendAudio(min, step, answer.content);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async playUrl(
|
public async playUrl(
|
||||||
min,
|
min,
|
||||||
conversationalService: IGBConversationalService,
|
conversationalService: IGBConversationalService,
|
||||||
step: GBDialogStep,
|
step: GBDialogStep,
|
||||||
|
|
|
@ -30,82 +30,10 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import { GBMinInstance } from 'botlib';
|
|
||||||
import OpenAI from 'openai';
|
|
||||||
|
|
||||||
import { AzureKeyCredential } from '@azure/core-auth';
|
|
||||||
import { DialogKeywords } from '../../basic.gblib/services/DialogKeywords';
|
|
||||||
import path from 'path';
|
|
||||||
import { GBServer } from '../../../src/app.js';
|
|
||||||
import fs from 'fs/promises';
|
|
||||||
import urlJoin from 'url-join';
|
|
||||||
import { GBAdminService } from '../../admin.gbapp/services/GBAdminService';
|
|
||||||
import { GBLogEx } from '../../core.gbapp/services/GBLogEx';
|
|
||||||
import { GBUtil } from '../../../src/util';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Image processing services of conversation to be called by BASIC.
|
* Image processing services of conversation to be called by BASIC.
|
||||||
*/
|
*/
|
||||||
export class ImageServices {
|
export class ImageServices {
|
||||||
public async getImageFromPrompt({ pid, prompt }) {
|
|
||||||
const { min, user, params } = await DialogKeywords.getProcessInfo(pid);
|
|
||||||
|
|
||||||
const azureOpenAIKey = await min.core.getParam(min.instance, 'Azure Open AI Key', null);
|
|
||||||
const azureOpenAIImageModel = await min.core.getParam(min.instance, 'Azure Open Image Model', null);
|
|
||||||
const azureOpenAIEndpoint = await min.core.getParam(min.instance, 'Azure Open AI Endpoint', null);
|
|
||||||
|
|
||||||
if (azureOpenAIKey) {
|
|
||||||
// Initialize the Azure OpenAI client
|
|
||||||
|
|
||||||
const client = new OpenAI({ apiKey: azureOpenAIKey, baseURL: azureOpenAIEndpoint });
|
|
||||||
|
|
||||||
// Make a request to the image generation endpoint
|
|
||||||
|
|
||||||
const response = await client.images.generate({
|
|
||||||
prompt: prompt,
|
|
||||||
n: 1,
|
|
||||||
size: '1024x1024'
|
|
||||||
});
|
|
||||||
|
|
||||||
const gbaiName = GBUtil.getGBAIPath(min.botId);
|
|
||||||
const localName = path.join('work', gbaiName, 'cache', `DALL-E${GBAdminService.getRndReadableIdentifier()}.png`);
|
|
||||||
|
|
||||||
const url = response.data[0].url;
|
|
||||||
const res = await fetch(url);
|
|
||||||
let buf: any = Buffer.from(await res.arrayBuffer());
|
|
||||||
await fs.writeFile(localName, buf, { encoding: null });
|
|
||||||
|
|
||||||
GBLogEx.info(min, `DALL-E image generated at ${url}.`);
|
|
||||||
|
|
||||||
return { localName, url };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getCaptionForImage({ pid, imageUrl }) {
|
|
||||||
const { min, user, params } = await DialogKeywords.getProcessInfo(pid);
|
|
||||||
|
|
||||||
const azureOpenAIKey = await min.core.getParam(min.instance, 'Azure Open AI Key', null);
|
|
||||||
const azureOpenAITextModel = 'gpt-4'; // Specify GPT-4 model here
|
|
||||||
const azureOpenAIEndpoint = await min.core.getParam(min.instance, 'Azure Open AI Endpoint', null);
|
|
||||||
|
|
||||||
if (azureOpenAIKey && azureOpenAITextModel && imageUrl) {
|
|
||||||
// Initialize the Azure OpenAI client
|
|
||||||
const client = new OpenAI({ apiKey: azureOpenAIKey, baseURL: azureOpenAIEndpoint });
|
|
||||||
|
|
||||||
// Construct a prompt to describe the image and generate a caption
|
|
||||||
const prompt = `Provide a descriptive caption for the image at the following URL: ${imageUrl}`;
|
|
||||||
|
|
||||||
// Generate a caption using GPT-4
|
|
||||||
const response = await client.completions.create({
|
|
||||||
model: azureOpenAITextModel,
|
|
||||||
prompt: prompt,
|
|
||||||
max_tokens: 50
|
|
||||||
});
|
|
||||||
|
|
||||||
const caption = response['data'].choices[0].text.trim();
|
|
||||||
GBLogEx.info(min, `Generated caption: ${caption}`);
|
|
||||||
|
|
||||||
return { caption };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
7
templates/ai-search.gbai/ai-search.gbdialog/start.bas
Normal file
7
templates/ai-search.gbai/ai-search.gbdialog/start.bas
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
image = GET IMAGE "AI Search BOT and write General Bots."
|
||||||
|
|
||||||
|
PLAY image
|
||||||
|
|
||||||
|
BEGIN SYSTEM PROMPT
|
||||||
|
|
||||||
|
END SYSTEM PROMPT
|
|
@ -1,3 +1,3 @@
|
||||||
name,value
|
name,value
|
||||||
Answer Mode,document-ref
|
Answer Mode,document-ref
|
||||||
Theme Color,violet
|
Theme Color,blue
|
||||||
|
|
|
|
@ -186,9 +186,9 @@ screen and (min-width: 420px) and (max-width: 1000px) {
|
||||||
|
|
||||||
@media screen and (min-width: 1000px) {
|
@media screen and (min-width: 1000px) {
|
||||||
.player {
|
.player {
|
||||||
width: 45% !important;
|
width: 46% !important;
|
||||||
height: 71% !important;
|
height: 73% !important;
|
||||||
border: 7px solid var(--color-light-border);
|
border: 8px solid var(--color-light-border);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 3%;
|
left: 3%;
|
||||||
top: 24%;
|
top: 24%;
|
||||||
|
|
Loading…
Add table
Reference in a new issue