From 22141095f04ff7c0ef72bbd8201d5d4d136d416f Mon Sep 17 00:00:00 2001 From: Rodrigo Rodriguez Date: Fri, 13 Sep 2024 16:56:04 -0300 Subject: [PATCH] fix (templates): llm-server almost OK. --- directline-3.0.json | 15 +++ .../services/GBConversationalService.ts | 37 +++++--- packages/core.gbapp/services/GBMinService.ts | 92 +++++++++---------- packages/core.gbapp/services/router/bridge.ts | 18 ++-- .../security.gbapp/services/SecService.ts | 4 +- .../llm-server.gbdialog/start.bas | 17 ++-- 6 files changed, 102 insertions(+), 81 deletions(-) diff --git a/directline-3.0.json b/directline-3.0.json index 39755e98..80662bb1 100644 --- a/directline-3.0.json +++ b/directline-3.0.json @@ -35,6 +35,21 @@ "application/xml", "text/xml" ], + "parameters": [ + { + "name": "userSystemId", + "in": "query", + "description": "User System ID", + "required": false, + "type": "string" + },{ + "name": "userName", + "in": "query", + "description": "User Name", + "required": false, + "type": "string" + }], + "responses": { "200": { "description": "The conversation was successfully created, updated, or retrieved.", diff --git a/packages/core.gbapp/services/GBConversationalService.ts b/packages/core.gbapp/services/GBConversationalService.ts index 69b53007..193f934c 100644 --- a/packages/core.gbapp/services/GBConversationalService.ts +++ b/packages/core.gbapp/services/GBConversationalService.ts @@ -48,8 +48,8 @@ import { CollectionUtil, AzureText } from 'pragmatismo-io-framework'; import { GuaribasUser } from '../../security.gbapp/models/index.js'; import { GBMinService } from './GBMinService.js'; import urlJoin from 'url-join'; -import {createWriteStream, createReadStream} from 'fs'; -import fs from 'fs/promises'; +import { createWriteStream, createReadStream } from 'fs'; +import fs from 'fs/promises'; import twilio from 'twilio'; import Nexmo from 'nexmo'; import { join } from 'path'; @@ -452,7 +452,7 @@ export class GBConversationalService { const waveFilename = `work/tmp${name}.pcm`; let audio = await textToSpeech.repairWavHeaderStream(res.result as any); - await fs.writeFile(waveFilename, audio); + await fs.writeFile(waveFilename, audio); const oggFilenameOnly = `tmp${name}.ogg`; const oggFilename = `work/${oggFilenameOnly}`; @@ -482,7 +482,7 @@ export class GBConversationalService { const dest = `work/tmp${name}.wav`; const src = `work/tmp${name}.ogg`; - await fs.writeFile(src, oggFile.read()); + await fs.writeFile(src, oggFile.read()); const makeMp3 = shell([ 'node_modules/ffmpeg-static/ffmpeg', // TODO: .exe on MSWin. @@ -1282,22 +1282,31 @@ export class GBConversationalService { * Sends a message in a user with an already started conversation (got ConversationReference set) */ public async sendOnConversation(min: GBMinInstance, user: GuaribasUser, message: any) { - if (message['buttons'] || message['sections']) { - await min['whatsAppDirectLine'].sendToDevice(user.userSystemId, message, user.conversationReference); - } else if (user.conversationReference.startsWith('spaces')) { - await min['googleDirectLine'].sendToDevice(user.userSystemId, null, user.conversationReference, message); - } else { - const ref = JSON.parse(user.conversationReference); - MicrosoftAppCredentials.trustServiceUrl(ref.serviceUrl); - try { + if (GBConfigService.get('STORAGE_NAME')) { + const ref = JSON.parse(user.conversationReference); + MicrosoftAppCredentials.trustServiceUrl(ref.serviceUrl); await min.bot['continueConversation'](ref, async t1 => { const ref2 = TurnContext.getConversationReference(t1.activity); await min.bot.continueConversation(ref2, async t2 => { await t2.sendActivity(message); }); }); - } catch (error) { - console.log(error); + + } else { + + const ref = JSON.parse(user.conversationReference); + await min.bot['continueConversation'](ref, async (t1) => { + const ref2 = TurnContext.getConversationReference(t1.activity); + await min.bot.continueConversation(ref2, async (t2) => { + await t2.sendActivity(message); + }); + }); + + if (message['buttons'] || message['sections']) { + await min['whatsAppDirectLine'].sendToDevice(user.userSystemId, message, user.conversationReference); + } + else if (user.conversationReference && user.conversationReference.startsWith('spaces')) { + await min['googleDirectLine'].sendToDevice(user.userSystemId, null, user.conversationReference, message); } } } diff --git a/packages/core.gbapp/services/GBMinService.ts b/packages/core.gbapp/services/GBMinService.ts index 9720e684..d9254fba 100644 --- a/packages/core.gbapp/services/GBMinService.ts +++ b/packages/core.gbapp/services/GBMinService.ts @@ -151,8 +151,6 @@ export class GBMinService { this.deployer = deployer; } - public async enableAPI(min: GBMinInstance) {} - /** * Constructs a new minimal instance for each bot. */ @@ -400,7 +398,8 @@ export class GBMinService { res.end(); }); - await GBMinService.ensureAPI(min); + await this.ensureAPI(); + GBLog.verbose(`GeneralBots(${instance.engineName}) listening on: ${url}.`); // Generates MS Teams manifest. @@ -1032,12 +1031,13 @@ export class GBMinService { const member = context.activity.from; const sec = new SecService(); - const user = await sec.ensureUser(min, member.id, member.name, '', 'web', member.name, null); + let user = await sec.ensureUser(min, member.id, member.name, '', 'web', member.name, null); const userId = user.userId; const params = user.params ? JSON.parse(user.params) : {}; try { const conversationReference = JSON.stringify(TurnContext.getConversationReference(context.activity)); + user = await sec.updateConversationReferenceById(user.userId, conversationReference); // First time processing. @@ -1648,15 +1648,9 @@ export class GBMinService { } } - public static async ensureAPI(min: GBMinInstance) { - const api = min.core.getParam(min.instance, 'Server API', null); - if (!api) { - - return; - } - - GBLogEx.info(min, `Enabling API...`); - + public async ensureAPI() { + const mins = GBServer.globals.minInstances; + function getRemoteId(ctx: Koa.Context) { return '1'; // Each bot has its own API. } @@ -1669,7 +1663,7 @@ export class GBMinService { }); } else { resolve(true); - + GBLogEx.info(0, 'Loading General Bots API...'); } }); }; @@ -1677,45 +1671,47 @@ export class GBMinService { await close(); let proxies = {}; - let dialogs = {}; - await CollectionUtil.asyncForEach(Object.values(min.scriptMap), async script => { - dialogs[script] = async data => { + await CollectionUtil.asyncForEach(mins, async min => { + let dialogs = {}; - if (!data.userSystemId){ - throw new Error('UserSystemId is required.'); - } + await CollectionUtil.asyncForEach(Object.values(min.scriptMap), async script => { + const api = min.core.getParam(min.instance, 'Server API', null); + if (api) { + dialogs[script] = async data => { + let sec = new SecService(); + const user = await sec.ensureUser( + min, + data.userSystemId, + data.userName ? data.userName : 'apiuser', + '', + 'api', + data.userSystemId, + null + ); + let pid = data?.pid; + if (script === 'start') { + pid = GBVMService.createProcessInfo(user, min, 'api', null); - let sec = new SecService(); - const user = await sec.ensureUser( - min, - data.userSystemId, - data.userSystemId, - '', - 'api', - data.userSystemId, - null - ); + const client = await GBUtil.getDirectLineClient(min); + const response = await client.apis.Conversations.Conversations_StartConversation({ + userSystemId: user.userSystemId, + userName: user.userName + }); + + min['apiConversations'][pid] = { conversation: response.obj, client: client }; + min['conversationWelcomed'][response.obj.id] = true; + } - let pid = data?.pid; - if (script === 'start') { - pid = GBVMService.createProcessInfo(user, min, 'api', null); + let ret = await GBVMService.callVM(script, min, null, pid, false, data); - const client = await GBUtil.getDirectLineClient(min); - const response = await client.apis.Conversations.Conversations_StartConversation(); - - min['apiConversations'][pid] = { conversation: response.obj, client: client }; - min['conversationWelcomed'][response.obj.id] = true; - } - - let ret = await GBVMService.callVM(script, min, null, pid, false, data); - - if (script === 'start') { - ret = pid; - } - return ret; - - }; + if (script === 'start') { + ret = pid; + } + return ret; + }; + } + }); const proxy = { dk: new DialogKeywords(), diff --git a/packages/core.gbapp/services/router/bridge.ts b/packages/core.gbapp/services/router/bridge.ts index 5d4dc9ba..97a54974 100644 --- a/packages/core.gbapp/services/router/bridge.ts +++ b/packages/core.gbapp/services/router/bridge.ts @@ -12,6 +12,7 @@ const conversationsCleanupInterval = 10000; const conversations: { [key: string]: IConversation } = {}; const botDataStore: { [key: string]: IBotData } = {}; + export const getRouter = ( serviceUrl: string, botUrl: string, @@ -46,7 +47,10 @@ export const getRouter = ( }; console.log('Created conversation with conversationId: ' + conversationId); - const activity = createConversationUpdateActivity(serviceUrl, conversationId); + const activity = createConversationUpdateActivity + (serviceUrl, conversationId, req.query?.userSystemId, + req.query?.userName + ); fetch(botUrl, { method: 'POST', body: JSON.stringify(activity), @@ -61,10 +65,10 @@ export const getRouter = ( }); }; - router.post('/v3/directline/conversations', reqs); - router.post(`/api/messages/${botId}/v3/directline/conversations`, reqs); - router.post(`/directline/${botId}/conversations`, reqs); - router.post(`/directline/conversations`, reqs); + router.post('/v3/directline/conversations/', reqs); + router.post(`/api/messages/${botId}/v3/directline/conversations/`, reqs); + router.post(`/directline/${botId}/conversations/`, reqs); + router.post(`/directline/conversations/`, reqs); // Reconnect API router.get('/v3/directline/conversations/:conversationId', (req, res) => { @@ -329,7 +333,7 @@ const createMessageActivity = ( }; }; -const createConversationUpdateActivity = (serviceUrl: string, conversationId: string): IConversationUpdateActivity => { +const createConversationUpdateActivity = (serviceUrl: string, conversationId: string, userSystemId, userName): IConversationUpdateActivity => { const activity: IConversationUpdateActivity = { type: 'conversationUpdate', channelId: 'emulator', @@ -338,7 +342,7 @@ const createConversationUpdateActivity = (serviceUrl: string, conversationId: st id: uuidv4.v4(), membersAdded: [], membersRemoved: [], - from: { id: 'offline-directline', name: 'Offline Directline Server' } + from: { id: userSystemId, name: userName } }; return activity; }; diff --git a/packages/security.gbapp/services/SecService.ts b/packages/security.gbapp/services/SecService.ts index 82e658c6..358dd8fc 100644 --- a/packages/security.gbapp/services/SecService.ts +++ b/packages/security.gbapp/services/SecService.ts @@ -80,7 +80,7 @@ export class SecService extends GBService { user.conversationReference = conversationReference; GBServer.globals.users [user.userId] = user; - await user.save(); + return await user.save(); } public async updateConversationReferenceById(userId: number, conversationReference: string) { @@ -89,7 +89,7 @@ export class SecService extends GBService { user.conversationReference = conversationReference; GBServer.globals.users [user.userId] = user; - await user.save(); + return await user.save(); } public async updateUserLocale(userId: number, locale: any): Promise { diff --git a/templates/llm-server.gbai/llm-server.gbdialog/start.bas b/templates/llm-server.gbai/llm-server.gbdialog/start.bas index 480f46d1..a932a19c 100644 --- a/templates/llm-server.gbai/llm-server.gbdialog/start.bas +++ b/templates/llm-server.gbai/llm-server.gbdialog/start.bas @@ -19,9 +19,9 @@ Here is an example of the Order JSON, clear the items and send one with the orde orderedItems: [ { item: { - id: 23872, - price: 20, - name: GuaranĂ¡ + id: 102, + price: 0.30, + name: Banana }, sideItems: [ { @@ -35,9 +35,9 @@ Here is an example of the Order JSON, clear the items and send one with the orde }, { item: { - id: 25510, - price: 12, - name: Orange Can 350ml + id: 103, + price: 0.30, + name: Carrot }, sideItems: [], quantity: 1, @@ -46,9 +46,6 @@ Here is an example of the Order JSON, clear the items and send one with the orde ], userId: ${operator}, accountIdentifier: Areia, - deliveryTypeId: 2, - deliveryTypeFields: { - Table: 5 - } + deliveryTypeId: 2 } END SYSTEM PROMPT