fix(basic.gblib): FUNCTION GPT.
This commit is contained in:
parent
26b05aa394
commit
49af4cfab7
7 changed files with 183 additions and 180 deletions
|
@ -82,6 +82,7 @@
|
|||
"@google-cloud/translate": "7.0.4",
|
||||
"@hubspot/api-client": "7.1.2",
|
||||
"@koa/cors": "4.0.0",
|
||||
"@langchain/openai": "0.0.15",
|
||||
"@microsoft/microsoft-graph-client": "3.0.4",
|
||||
"@nlpjs/basic": "4.26.1",
|
||||
"@nosferatu500/textract": "3.1.2",
|
||||
|
@ -211,7 +212,8 @@
|
|||
"winston": "3.8.2",
|
||||
"winston-logs-display": "1.0.0",
|
||||
"ws": "8.12.1",
|
||||
"yarn": "1.22.19"
|
||||
"yarn": "1.22.19",
|
||||
"zod-to-json-schema": "^3.22.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/qrcode": "1.5.0",
|
||||
|
|
|
@ -425,14 +425,15 @@ export class AzureDeployerService implements IGBInstallationDeployer {
|
|||
instance.storageDialect = 'mssql';
|
||||
instance.storageServer = `${storageServer}.database.windows.net`;
|
||||
|
||||
GBLog.info(`Deploying Search...`);
|
||||
const searchName = `${name}-search`.toLowerCase();
|
||||
await this.createSearch(name, searchName, instance.cloudLocation);
|
||||
const searchKeys = await this.searchClient.adminKeys.get(name, searchName);
|
||||
instance.searchHost = `${searchName}.search.windows.net`;
|
||||
instance.searchIndex = 'azuresql-index';
|
||||
instance.searchIndexer = 'azuresql-indexer';
|
||||
instance.searchKey = searchKeys.primaryKey;
|
||||
// TODO: Enable in .env
|
||||
// GBLog.info(`Deploying Search...`);
|
||||
// const searchName = `${name}-search`.toLowerCase();
|
||||
// await this.createSearch(name, searchName, instance.cloudLocation);
|
||||
// const searchKeys = await this.searchClient.adminKeys.get(name, searchName);
|
||||
// instance.searchHost = `${searchName}.search.windows.net`;
|
||||
// instance.searchIndex = 'azuresql-index';
|
||||
// instance.searchIndexer = 'azuresql-indexer';
|
||||
// instance.searchKey = searchKeys.primaryKey;
|
||||
|
||||
// GBLog.info(`Deploying Speech...`);
|
||||
// const speech = await this.createSpeech(name, `${name}speech`, instance.cloudLocation);
|
||||
|
|
|
@ -52,6 +52,8 @@ import { GBLogEx } from '../../core.gbapp/services/GBLogEx.js';
|
|||
import { GuaribasUser } from '../../security.gbapp/models/index.js';
|
||||
import { SystemKeywords } from './SystemKeywords.js';
|
||||
import { Sequelize, QueryTypes } from '@sequelize/core';
|
||||
import { z } from "zod";
|
||||
import { zodToJsonSchema } from "zod-to-json-schema";
|
||||
|
||||
/**
|
||||
* @fileoverview Decision was to priorize security(isolation) and debugging,
|
||||
|
@ -415,7 +417,7 @@ export class GBVMService extends GBService {
|
|||
min.instance,
|
||||
'Synchronize Database',
|
||||
false
|
||||
);
|
||||
);
|
||||
|
||||
if (sync && shouldSync) {
|
||||
|
||||
|
@ -641,7 +643,7 @@ export class GBVMService extends GBService {
|
|||
|
||||
try{
|
||||
await ensureTokens(true);
|
||||
${ code }
|
||||
${code}
|
||||
}
|
||||
catch(e){
|
||||
console.log(e);
|
||||
|
@ -723,42 +725,55 @@ export class GBVMService extends GBService {
|
|||
}
|
||||
|
||||
public static getMetadata(mainName: string, propertiesText, description) {
|
||||
const properties = [];
|
||||
let properties;
|
||||
if (!propertiesText) {
|
||||
|
||||
if (propertiesText) {
|
||||
const getType = asClause => {
|
||||
if (asClause.indexOf('AS STRING')) {
|
||||
return 'string';
|
||||
} else {
|
||||
return 'enum';
|
||||
}
|
||||
};
|
||||
|
||||
for (let i = 0; i < propertiesText.length; i++) {
|
||||
const propertiesExp = propertiesText[i];
|
||||
const t = getType(propertiesExp[2]);
|
||||
let element = {};
|
||||
element['type'] = t;
|
||||
|
||||
if (t === 'enum') {
|
||||
element['enum'] = propertiesExp[2];
|
||||
} else if (t === 'string') {
|
||||
element['description'] = propertiesExp[2];
|
||||
}
|
||||
|
||||
properties.push(element);
|
||||
}
|
||||
return {}
|
||||
}
|
||||
|
||||
let json = {
|
||||
name: `${mainName}`,
|
||||
description: description ? description[1] : '',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: properties ? properties : []
|
||||
const getType = asClause => {
|
||||
if (asClause.indexOf('AS STRING') !== -1) {
|
||||
return 'string';
|
||||
}
|
||||
else if (asClause.indexOf('AS OBJECT') !== -1) {
|
||||
return 'object';
|
||||
}
|
||||
else if (asClause.indexOf('AS INTEGER') !== -1 || asClause.indexOf('AS NUMBER') !== -1) {
|
||||
return 'number';
|
||||
} else {
|
||||
return 'enum';
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
for (let i = 0; i < propertiesText.length; i++) {
|
||||
const propertiesExp = propertiesText[i];
|
||||
const t = getType(propertiesExp[2]);
|
||||
let element;
|
||||
|
||||
if (t === 'enum') {
|
||||
element = z.enum(propertiesExp[2].split(','));
|
||||
} else if (t === 'string') {
|
||||
element = z.string();
|
||||
} else if (t === 'object') {
|
||||
element = z.quotelessJson({});
|
||||
} else if (t === 'number') {
|
||||
element = z.number();
|
||||
}
|
||||
element.describe(propertiesExp[3]);
|
||||
element['type'] = t;
|
||||
properties[propertiesExp[1]] = element;
|
||||
}
|
||||
|
||||
|
||||
let json = {
|
||||
type: "function",
|
||||
function: {
|
||||
name: `${mainName}`,
|
||||
description: description ? description[1] : '',
|
||||
parameters: zodToJsonSchema(z.object(properties))
|
||||
}
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
|
@ -766,15 +781,15 @@ export class GBVMService extends GBService {
|
|||
|
||||
let required = line.indexOf('*') !== -1;
|
||||
let unique = /\bunique\b/gi.test(line);
|
||||
let primaryKey = /\bkey\b/gi.test(line);
|
||||
let autoIncrement = /\bauto\b/gi.test(line);
|
||||
let primaryKey = /\bkey\b/gi.test(line);
|
||||
let autoIncrement = /\bauto\b/gi.test(line);
|
||||
|
||||
if (primaryKey){
|
||||
if (primaryKey) {
|
||||
autoIncrement = true;
|
||||
unique = true;
|
||||
required = true;
|
||||
}
|
||||
|
||||
|
||||
line = line.replace('*', '');
|
||||
|
||||
const fieldRegExp = /^\s*(\w+)\s*(\w+)(?:\((.*)\))?/gim;
|
||||
|
@ -783,9 +798,11 @@ export class GBVMService extends GBService {
|
|||
const name = reg[1];
|
||||
const t = reg[2];
|
||||
|
||||
let definition = { allowNull: !required,
|
||||
unique: unique, primaryKey: primaryKey,
|
||||
autoIncrement: autoIncrement };
|
||||
let definition = {
|
||||
allowNull: !required,
|
||||
unique: unique, primaryKey: primaryKey,
|
||||
autoIncrement: autoIncrement
|
||||
};
|
||||
definition['type'] = t;
|
||||
|
||||
if (reg[3]) {
|
||||
|
@ -829,7 +846,7 @@ export class GBVMService extends GBService {
|
|||
|
||||
line = line.replace(/^\s*\d+\s*/gi, '');
|
||||
|
||||
if (!table && !talk){
|
||||
if (!table && !talk) {
|
||||
for (let j = 0; j < keywords.length; j++) {
|
||||
line = line.replace(keywords[j][0], keywords[j][1]); // TODO: Investigate delay here.
|
||||
}
|
||||
|
@ -838,7 +855,7 @@ export class GBVMService extends GBService {
|
|||
// Pre-process "off-line" static KEYWORDS.
|
||||
|
||||
let emmit = true;
|
||||
const params = /^\s*PARAM\s*(.*)\s*AS\s*(.*)/gim;
|
||||
const params = /^\s*PARAM\s*(.*)\s*AS\s*(.*)\s*LIKE\s*(.*)/gim;
|
||||
const param = params.exec(line);
|
||||
if (param) {
|
||||
properties.push(param);
|
||||
|
@ -856,7 +873,7 @@ export class GBVMService extends GBService {
|
|||
let endTalkReg = endTalkKeyword.exec(line);
|
||||
if (endTalkReg && talk) {
|
||||
line = talk + '`})';
|
||||
|
||||
|
||||
talk = null;
|
||||
emmit = true;
|
||||
}
|
||||
|
@ -912,8 +929,8 @@ export class GBVMService extends GBService {
|
|||
let add = emmit ? line.split(/\r\n|\r|\n/).length : 0;
|
||||
current = current + (add ? add : 0);
|
||||
|
||||
if (emmit){
|
||||
emmitIndex ++;
|
||||
if (emmit) {
|
||||
emmitIndex++;
|
||||
map[emmitIndex] = current;
|
||||
outputLines[emmitIndex - 1] = line;
|
||||
}
|
||||
|
@ -1000,15 +1017,15 @@ export class GBVMService extends GBService {
|
|||
|
||||
let code = min.sandBoxMap[text];
|
||||
const channel = step ? step.context.activity.channelId : 'web';
|
||||
|
||||
|
||||
|
||||
|
||||
const dk = new DialogKeywords();
|
||||
const sys = new SystemKeywords();
|
||||
await dk.setFilter({ pid: pid, value: null });
|
||||
|
||||
|
||||
// Find all tokens in .gbot Config.
|
||||
|
||||
|
||||
const strFind = ' Client ID';
|
||||
const tokens = await min.core['findParam'](min.instance, strFind);
|
||||
let tokensList = [];
|
||||
|
|
|
@ -1011,6 +1011,13 @@ export class GBMinService {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
let pid = step.context.activity['pid'];
|
||||
if (!pid){
|
||||
pid = GBVMService.createProcessInfo(user, min, step.context.activity.channelId, null);
|
||||
}
|
||||
step.context.activity['pid'] = pid;
|
||||
|
||||
// Required for MSTEAMS handling of persisted conversations.
|
||||
|
||||
if (step.context.activity.channelId === 'msteams') {
|
||||
|
@ -1065,12 +1072,7 @@ export class GBMinService {
|
|||
|
||||
const startDialog = min.core.getParam(min.instance, 'Start Dialog', null);
|
||||
|
||||
let pid = step.context.activity['pid'];
|
||||
if (!pid){
|
||||
pid = GBVMService.createProcessInfo(user, min, step.context.activity.channelId, null);
|
||||
}
|
||||
step.context.activity['pid'] = pid;
|
||||
|
||||
|
||||
if (context.activity.type === 'installationUpdate') {
|
||||
GBLog.info(`Bot installed on Teams.`);
|
||||
} else if (context.activity.type === 'conversationUpdate' && context.activity.membersAdded.length > 0) {
|
||||
|
@ -1151,6 +1153,7 @@ export class GBMinService {
|
|||
* Called to handle all event sent by .gbui clients.
|
||||
*/
|
||||
private async processEventActivity(min, user, context, step: GBDialogStep) {
|
||||
const pid = step.context.activity['pid'];
|
||||
if (context.activity.name === 'whoAmI') {
|
||||
await step.beginDialog('/whoAmI');
|
||||
} else if (context.activity.name === 'showSubjects') {
|
||||
|
|
|
@ -31,11 +31,9 @@
|
|||
'use strict';
|
||||
|
||||
import { GBMinInstance } from 'botlib';
|
||||
import OpenAI from "openai";
|
||||
import { OpenAIChat } from 'langchain/llms/openai';
|
||||
import { CallbackManager } from 'langchain/callbacks';
|
||||
import { ChatPromptTemplate, HumanMessagePromptTemplate, SystemMessagePromptTemplate } from 'langchain/prompts';
|
||||
import { LLMChain } from 'langchain/chains';
|
||||
import { ConversationChain, LLMChain } from 'langchain/chains';
|
||||
import { BufferWindowMemory } from 'langchain/memory';
|
||||
import { CollectionUtil } from 'pragmatismo-io-framework';
|
||||
import { DialogKeywords } from '../../basic.gblib/services/DialogKeywords.js';
|
||||
|
@ -44,6 +42,10 @@ import * as Fs from 'fs';
|
|||
import { HNSWLib } from 'langchain/vectorstores/hnswlib';
|
||||
import { GuaribasSubject } from '../../kb.gbapp/models/index.js';
|
||||
import { GBConfigService } from '../../core.gbapp/services/GBConfigService.js';
|
||||
import { ChatOpenAI } from "@langchain/openai";
|
||||
import { JsonOutputFunctionsParser } from 'langchain/dist/output_parsers/openai_functions.js';
|
||||
import { GBVMService } from '../../basic.gblib/services/GBVMService.js';
|
||||
|
||||
|
||||
export class ChatServices {
|
||||
|
||||
|
@ -60,19 +62,39 @@ export class ChatServices {
|
|||
.replaceAll('\n', ' ');
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate text
|
||||
*
|
||||
* CONTINUE keword.
|
||||
*
|
||||
* result = CONTINUE text
|
||||
*
|
||||
*/
|
||||
public static async continue(min: GBMinInstance, text: string, chatId) {
|
||||
|
||||
public static async sendMessage(min: GBMinInstance, text: string) {
|
||||
let key;
|
||||
if (process.env.OPENAI_KEY) {
|
||||
key = process.env.OPENAI_KEY;
|
||||
}
|
||||
else {
|
||||
key = min.core.getParam(min.instance, 'Open AI Key', null);
|
||||
}
|
||||
|
||||
|
||||
public static async answerByGPT(min: GBMinInstance, pid,
|
||||
query: string,
|
||||
searchScore: number,
|
||||
subjects: GuaribasSubject[]
|
||||
) {
|
||||
|
||||
if (!process.env.OPENAI_KEY) {
|
||||
return { answer: undefined, questionId: 0 };
|
||||
}
|
||||
|
||||
if (!key) {
|
||||
throw new Error('Open AI Key not configured in .gbot.');
|
||||
}
|
||||
const systemPrompt = SystemMessagePromptTemplate.fromTemplate(
|
||||
`You are $${min.botId}`);
|
||||
|
||||
const contentLocale = min.core.getParam(
|
||||
min.instance,
|
||||
'Default Content Language',
|
||||
GBConfigService.get('DEFAULT_CONTENT_LANGUAGE')
|
||||
);
|
||||
|
||||
|
||||
let functions = [];
|
||||
|
||||
// Adds .gbdialog as functions if any to GPT Functions.
|
||||
|
@ -88,82 +110,17 @@ export class ChatServices {
|
|||
|
||||
});
|
||||
|
||||
// Calls Model.
|
||||
|
||||
const openai = new OpenAI({
|
||||
apiKey: key
|
||||
});
|
||||
const chatCompletion = await openai.chat.completions.create({
|
||||
model: "gpt-3.5-turbo",
|
||||
messages: [{ role: "user", content: text }],
|
||||
functions: functions
|
||||
});
|
||||
return chatCompletion.choices[0].message.content;
|
||||
}
|
||||
let SystemPromptTailored = ''; // TODO: Load from user context.
|
||||
|
||||
// Generates function definition for each function
|
||||
// in plain text to be used in system prompt.
|
||||
|
||||
let functionDef = Object.keys(functions)
|
||||
.map((toolname) => `${toolname}: ${functions[toolname].description}`)
|
||||
.join("\n");
|
||||
|
||||
/**
|
||||
* Generate text
|
||||
*
|
||||
* CONTINUE keword.
|
||||
*
|
||||
* result = CONTINUE text
|
||||
*
|
||||
*/
|
||||
public static async continue(min: GBMinInstance, text: string, chatId) {
|
||||
let key;
|
||||
if (process.env.OPENAI_KEY) {
|
||||
key = process.env.OPENAI_KEY;
|
||||
}
|
||||
else {
|
||||
key = min.core.getParam(min.instance, 'Open AI Key', null);
|
||||
}
|
||||
|
||||
if (!key) {
|
||||
throw new Error('Open AI Key not configured in .gbot.');
|
||||
}
|
||||
// const openai = new OpenAI({
|
||||
// apiKey: key
|
||||
// });
|
||||
// const chatCompletion = await openai.chat.completions.create({
|
||||
// model: "gpt-3.5-turbo",
|
||||
// messages: [{ role: "user", content: text }]
|
||||
|
||||
// });
|
||||
// return chatCompletion.choices[0].message.content;
|
||||
}
|
||||
|
||||
public static async answerByGPT(min: GBMinInstance,
|
||||
query: string,
|
||||
searchScore: number,
|
||||
subjects: GuaribasSubject[]
|
||||
) {
|
||||
|
||||
if (!process.env.OPENAI_KEY) {
|
||||
return { answer: undefined, questionId: 0 };
|
||||
}
|
||||
|
||||
|
||||
const contextVectorStore = min['vectorStore'];
|
||||
const question = query.trim().replaceAll('\n', ' ');
|
||||
const context = await this.getRelevantContext(contextVectorStore, question, 1);
|
||||
|
||||
const systemPrompt = SystemMessagePromptTemplate.fromTemplate(
|
||||
`You are $${min.botId}`);
|
||||
|
||||
const contentLocale = min.core.getParam(
|
||||
min.instance,
|
||||
'Default Content Language',
|
||||
GBConfigService.get('DEFAULT_CONTENT_LANGUAGE')
|
||||
);
|
||||
|
||||
|
||||
const tools = ""// TODO: add func list.
|
||||
|
||||
const chatPrompt = ChatPromptTemplate.fromPromptMessages([
|
||||
systemPrompt,
|
||||
HumanMessagePromptTemplate.fromTemplate(`Answer in ${contentLocale}.
|
||||
let promptTemplate = `Answer in ${contentLocale}.
|
||||
You have access to the context (RELEVANTDOCS) provided by the user.
|
||||
|
||||
When answering think about whether the question in RELEVANTDOCS, but never mention
|
||||
|
@ -174,16 +131,18 @@ export class ChatServices {
|
|||
|
||||
QUESTION: """{input}"""
|
||||
|
||||
${SystemPromptTailored}
|
||||
|
||||
You have the following tools that you can invoke based on the user inquiry.
|
||||
Tools:
|
||||
|
||||
${tools}
|
||||
|
||||
`),
|
||||
]);
|
||||
|
||||
${functionDef}
|
||||
|
||||
`;
|
||||
|
||||
const chatPrompt = ChatPromptTemplate.fromPromptMessages([
|
||||
systemPrompt,
|
||||
HumanMessagePromptTemplate.fromTemplate(promptTemplate),]);
|
||||
|
||||
const windowMemory = new BufferWindowMemory({
|
||||
returnMessages: false,
|
||||
|
@ -192,36 +151,53 @@ export class ChatServices {
|
|||
k: 2,
|
||||
});
|
||||
|
||||
const callbackManager = CallbackManager.fromHandlers({
|
||||
// This function is called when the LLM generates a new token (i.e., a prediction for the next word)
|
||||
async handleLLMNewToken(token: string) {
|
||||
|
||||
},
|
||||
const llm = new ChatOpenAI({
|
||||
modelName: "gpt-3.5-turbo-0125",
|
||||
temperature: 0,
|
||||
});
|
||||
|
||||
const llm = new OpenAIChat({
|
||||
streaming: true,
|
||||
callbackManager,
|
||||
modelName: 'gpt-3.5-turbo',
|
||||
|
||||
const llmWithTools = llm.bind({
|
||||
tools: functions
|
||||
});
|
||||
|
||||
|
||||
const chain = new LLMChain({
|
||||
prompt: chatPrompt,
|
||||
memory: windowMemory,
|
||||
llm,
|
||||
prompt: chatPrompt,
|
||||
llm: llmWithTools as any,
|
||||
});
|
||||
|
||||
const response = await chain.call({
|
||||
input: question,
|
||||
context,
|
||||
history: '',
|
||||
immediate_history: '',
|
||||
});
|
||||
if (response) {
|
||||
const contextVectorStore = min['vectorStore'];
|
||||
const question = query.trim().replaceAll('\n', ' ');
|
||||
const context = await this.getRelevantContext(contextVectorStore, question, 1);
|
||||
|
||||
return { answer: response.text, questionId: 0 };
|
||||
let prompt;
|
||||
|
||||
// allow the LLM to iterate until it finds a final answer
|
||||
while (true) {
|
||||
const response = await chain.call({
|
||||
input: question,
|
||||
context,
|
||||
history: '',
|
||||
immediate_history: '',
|
||||
});
|
||||
|
||||
// add this to the prompt
|
||||
prompt += response;
|
||||
|
||||
const action = response.match(/Action: (.*)/)?.[1];
|
||||
if (action) {
|
||||
// execute the action specified by the LLMs
|
||||
const actionInput = response.match(/Action Input: "?(.*)"?/)?.[1];
|
||||
const text = '';
|
||||
|
||||
const result = await GBVMService.callVM(actionInput, min, false, pid,false, [text]);
|
||||
|
||||
|
||||
prompt += `Observation: ${result}\n`;
|
||||
} else {
|
||||
return response.match(/Final Answer: (.*)/)?.[1];
|
||||
}
|
||||
}
|
||||
|
||||
return { answer: undefined, questionId: 0 };
|
||||
}
|
||||
|
||||
|
|
|
@ -199,7 +199,8 @@ export class AskDialog extends IGBDialog {
|
|||
if (!text && step.context.activity.channelId === 'msteams') {
|
||||
const startDialog = min.core.getParam(min.instance, 'Start Dialog', null);
|
||||
if (startDialog) {
|
||||
await GBVMService.callVM(startDialog.toLowerCase().trim(), min, step, user, this.deployer, false);
|
||||
const pid = step.context.activity['pid'];
|
||||
await GBVMService.callVM(startDialog.toLowerCase().trim(), min, step, pid);
|
||||
}
|
||||
|
||||
return await step.endDialog();
|
||||
|
@ -229,7 +230,7 @@ export class AskDialog extends IGBDialog {
|
|||
|
||||
// TODO: https://github.com/GeneralBots/BotServer/issues/9 user.lastQuestion = text;
|
||||
|
||||
const resultsA = await service.ask(min, text, searchScore, null /* user.subjects */);
|
||||
const resultsA = await service.ask(min,step.context.activity['pid'], text, searchScore, null /* user.subjects */);
|
||||
|
||||
// If there is some result, answer immediately.
|
||||
|
||||
|
@ -343,7 +344,8 @@ export class AskDialog extends IGBDialog {
|
|||
if (text.endsWith('.docx')) {
|
||||
const mainName = GBVMService.getMethodNameFromVBSFilename(text);
|
||||
await step.endDialog();
|
||||
return await GBVMService.callVM(mainName, min, step, user, this.deployer, false);
|
||||
const pid = step.context.activity['pid'];
|
||||
return await GBVMService.callVM(mainName, min, step, pid);
|
||||
} else if (text.startsWith('/')) {
|
||||
return await step.replaceDialog(text, { answer: answer });
|
||||
} else {
|
||||
|
@ -445,8 +447,9 @@ export class AskDialog extends IGBDialog {
|
|||
);
|
||||
|
||||
await step.endDialog();
|
||||
const pid = step.context.activity['pid'];
|
||||
|
||||
await GBVMService.callVM(dialogName.toLowerCase(), min, step, user, this.deployer, false);
|
||||
await GBVMService.callVM(dialogName.toLowerCase(), min, step, pid);
|
||||
}
|
||||
}
|
||||
];
|
||||
|
|
|
@ -269,6 +269,7 @@ export class KBService implements IGBKBService {
|
|||
|
||||
public async ask(
|
||||
min: GBMinInstance,
|
||||
pid,
|
||||
query: string,
|
||||
searchScore: number,
|
||||
subjects: GuaribasSubject[]
|
||||
|
@ -375,7 +376,7 @@ export class KBService implements IGBKBService {
|
|||
returnedScore: ${returnedScore} < required (searchScore): ${searchScore}`
|
||||
);
|
||||
|
||||
return await ChatServices.answerByGPT(min,
|
||||
return await ChatServices.answerByGPT(min,pid,
|
||||
query,
|
||||
searchScore,
|
||||
subjects
|
||||
|
|
Loading…
Add table
Reference in a new issue