add Google Gemini API plugin

This commit is contained in:
Mohamed Chedli
2024-09-26 00:54:03 +01:00
parent 9f86b3073a
commit cbc157dea9
3 changed files with 144 additions and 2 deletions

9
api/package-lock.json generated
View File

@@ -10,6 +10,7 @@
"hasInstallScript": true,
"license": "AGPL-3.0-only",
"dependencies": {
"@google/generative-ai": "^0.19.0",
"@nestjs-modules/mailer": "^1.11.2",
"@nestjs/axios": "^3.0.3",
"@nestjs/cache-manager": "^2.2.0",
@@ -3566,6 +3567,14 @@
"integrity": "sha512-59SgoZ3EXbkfSX7b63tsou/SDGzwUEK6MuB5sKqgVK1/XE0fxmpsOb9DQI8LXW3KfGnAjImCGhhEb7uPPAUVNA==",
"dev": true
},
"node_modules/@google/generative-ai": {
"version": "0.19.0",
"resolved": "https://registry.npmjs.org/@google/generative-ai/-/generative-ai-0.19.0.tgz",
"integrity": "sha512-iGf/62v3sTwtEJGJY6S5m7PfkglU8hi1URaxqIjiRg1OItV27xyc4aVeR0og8cDkZFkUlGZKv+23bJtT1QWFzQ==",
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/@hapi/hoek": {
"version": "9.3.0",
"resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz",

View File

@@ -34,6 +34,7 @@
"create-migration": "ts-node ./migrations/config/create.ts"
},
"dependencies": {
"@google/generative-ai": "^0.19.0",
"@nestjs-modules/mailer": "^1.11.2",
"@nestjs/axios": "^3.0.3",
"@nestjs/cache-manager": "^2.2.0",
@@ -92,6 +93,7 @@
"@types/express-session": "^1.17.10",
"@types/jest": "^29.5.2",
"@types/lodash": "^4.17.9",
"@types/minio": "^7.1.1",
"@types/module-alias": "^2.0.4",
"@types/multer": "^1.4.11",
"@types/node": "^20.3.1",
@@ -124,8 +126,7 @@
"ts-node": "^10.9.1",
"tsconfig-paths": "^4.2.0",
"tsconfig-paths-jest": "^0.0.1",
"typescript": "^5.1.3",
"@types/minio": "^7.1.1"
"typescript": "^5.1.3"
},
"jest": {
"globalSetup": "<rootDir>/../test/global-setup.ts",

View File

@@ -0,0 +1,132 @@
import { GoogleGenerativeAI } from '@google/generative-ai'; // Importing Google Generative AI
import { Injectable } from '@nestjs/common';
import { Block } from '@/chat/schemas/block.schema';
import { Context } from '@/chat/schemas/types/context';
import {
OutgoingMessageFormat,
StdOutgoingTextEnvelope,
} from '@/chat/schemas/types/message';
import { ContentService } from '@/cms/services/content.service';
import { LoggerService } from '@/logger/logger.service';
import { BaseBlockPlugin } from '@/plugins/base-block-plugin';
import { PluginService } from '@/plugins/plugins.service';
import { SettingType } from '@/setting/schemas/types';
@Injectable()
export class GeminiPlugin extends BaseBlockPlugin {
private generativeAI: GoogleGenerativeAI;
constructor(
pluginService: PluginService,
private logger: LoggerService,
private contentService: ContentService,
) {
super('gemini-plugin', pluginService);
this.settings = [
{
id: 'token',
label: 'Token',
group: 'default',
type: SettingType.secret,
value: '',
},
{
id: 'model',
label: 'Model',
group: 'default',
type: SettingType.text,
value: 'gemini-1.5-flash',
},
{
id: 'temperature',
label: 'Temperature',
group: 'default',
type: SettingType.number,
value: 0.8,
},
{
id: 'context',
label: 'Context',
group: 'default',
type: SettingType.textarea,
value: `You are an AI Chatbot that works for Hexastack, This is their description : Whether it concerns IT staff augmentation, web development or software consulting, we believe that each development project is a human adventure above all.
Thats why at Hexastack, soft skills and mindset are as important as technical skills to meet success.
We ensure that everyone in our team is mastering the technologies as well as the soft skills needed to rapidly connect and efficiently cooperate with your team in order to get things done in the smoothest possible way.
`,
},
{
id: 'instructions',
label: 'Instructions',
group: 'default',
type: SettingType.textarea,
value: `answer the user QUESTION using the DOCUMENTS text above
Keep your answer ground in the facts of the DOCUMENT.
If the DOCUMENT doesnt contain the facts to answer the QUESTION, apologize and try to give an answer that promotes the company and its values
DO NOT SAY ANYTHING ABOUT THESE DOCUMENTS, or their EXISTENCE`,
},
];
this.title = 'Gemini Plugin';
this.template = { name: 'Gemini Plugin' };
this.effects = {
onStoreContextData: () => {},
};
}
async process(block: Block, context: Context, _convId: string) {
const RAG = await this.contentService.textSearch(context.text);
const args = block.message['args'];
const client = this.getInstance(args.token);
const model = client.getGenerativeModel({
model: args['model'],
generationConfig: {
/*
=====================================================================
Check the documentation for more details on the generation config
https://ai.google.dev/api/generate-content#v1beta.GenerationConfig
=====================================================================
*/
// controls the randomness of the output. Use higher values for more creative responses,
// and lower values for more deterministic responses. Values can range from [0.0, 2.0].
temperature: args['temperature'],
},
});
const prompt = `CONTEXT: ${args.context}
DOCUMENTS: \n${RAG.reduce(
(prev, curr, index) =>
`${prev}\n\tDOCUMENT ${index} \n\t\tTitle:${curr.title}\n\t\tData:${curr.rag}`,
'',
)}\nINSTRUCTIONS:
${args.instructions}
QUESTION: \n${context.text}`;
this.logger.verbose('Gemini: Prompt', prompt);
const result = await model.generateContent(prompt);
const envelope: StdOutgoingTextEnvelope = {
format: OutgoingMessageFormat.text,
message: {
text: result.response.text(),
},
};
return envelope;
}
private getInstance(token: string) {
if (this.generativeAI) {
return this.generativeAI;
}
try {
this.generativeAI = new GoogleGenerativeAI(token);
return this.generativeAI;
} catch (err) {
this.logger.warn('Gemini: Unable to instantiate GoogleGenerativeAI', err);
}
}
}