Skip to content

Commit 09536a1

Browse files
authored
Merge pull request #24 from oracle-devrel/backendServiceOptions
Backend service options
2 parents 3107aa5 + 4e4f23d commit 09536a1

File tree

10 files changed

+451
-145
lines changed

10 files changed

+451
-145
lines changed

app/package.json

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,23 @@
33
"version": "1.0.0",
44
"description": "Sample Client app showing communication with OCI Generative AI services via Websocket",
55
"dependencies": {
6-
"@oracle/oraclejet": "~16.0.0",
7-
"@oracle/oraclejet-core-pack": "~16.0.0",
6+
"@oracle/oraclejet": "~16.1.0",
7+
"@oracle/oraclejet-core-pack": "~16.1.0",
8+
"@stomp/stompjs": "^7.0.0",
89
"marked": "^4.3.0",
910
"uuid": "^9.0.1"
1011
},
1112
"devDependencies": {
12-
"@oracle/ojet-cli": "~16.0.0",
13-
"@oracle/oraclejet-audit": "^16.0.0",
13+
"@oracle/ojet-cli": "~16.1.0",
14+
"@oracle/oraclejet-audit": "^16.1.0",
1415
"@types/uuid": "^9.0.7",
16+
"express-http-proxy": "^2.0.0",
1517
"extract-zip": "^1.7.0",
1618
"fs-extra": "^8.1.0",
1719
"glob": "7.2.0",
1820
"typescript": "5.3.2",
1921
"underscore": "^1.10.2",
22+
"url": "^0.11.3",
2023
"yargs-parser": "13.1.2"
2124
},
2225
"engines": {

app/path_mapping.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,17 @@
380380
"path": "libs/chai/chai.js",
381381
"cdnPath": "chai/chai-4.3.10.min"
382382
}
383+
},
384+
"stompjs": {
385+
"cwd": "node_modules/@stomp/stompjs/bundles",
386+
"debug": {
387+
"src": "stomp.umd.js",
388+
"path": "libs/stompjs/stomp.umd.js"
389+
},
390+
"release": {
391+
"src": "stomp.umd.min.js",
392+
"path": "libs/stompjs/stomp.umd.min.js"
393+
}
383394
}
384395
}
385396
}

app/scripts/hooks/before_serve.js

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,28 @@
55
66
*/
77

8-
'use strict';
8+
"use strict";
99

1010
module.exports = function (configObj) {
1111
return new Promise((resolve, reject) => {
12-
console.log('Running before_serve hook.');
12+
console.log("Running before_serve hook.");
1313
// ojet custom connect and serve options
14-
// { connectOpts, serveOpts } = configObj;
15-
// const express = require('express');
16-
// const http = require('http');
14+
const { connectOpts, serveOpts } = configObj;
15+
const express = require("express");
16+
const http = require("http");
17+
const proxy = require("express-http-proxy");
18+
const url = require("url");
19+
20+
// New hostname+path as specified by question:
21+
const apiProxy = proxy("http://localhost:8080", {
22+
proxyReqPathResolver: (req) => url.parse("/api" + req.url).path,
23+
});
24+
const app = express();
25+
app.use("/api", apiProxy);
1726
// pass back custom http
18-
// configObj['http'] = http;
27+
configObj["http"] = http;
1928
// pass back custom express app
20-
// configObj['express'] = express();
29+
configObj["express"] = app;
2130
// pass back custom options for http.createServer
2231
// const serverOptions = {...};
2332
// configObj['serverOptions'] = serverOptions;

app/src/components/app.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
11
import { Header } from "./header";
22
import Content from "./content/index";
33
import { registerCustomElement } from "ojs/ojvcomponent";
4-
import "preact";
4+
import { createContext } from "preact";
55

66
type Props = {
77
appName: string;
88
};
9+
const convoUUID = window.crypto.randomUUID();
10+
export const ConvoCtx = createContext(convoUUID);
911

1012
export const App = registerCustomElement("app-root", (props: Props) => {
1113
props.appName = "Generative AI JET UI";
1214

1315
return (
1416
<div id="appContainer" class="oj-web-applayout-page">
15-
<Header appName={props.appName} />
16-
<Content />
17+
<ConvoCtx.Provider value={convoUUID}>
18+
{console.log("UUID: ", convoUUID)}
19+
<Header appName={props.appName} />
20+
<Content />
21+
</ConvoCtx.Provider>
1722
</div>
1823
);
1924
});

app/src/components/content/index.tsx

Lines changed: 79 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,44 @@ import "oj-c/drawer-popup";
99
import MutableArrayDataProvider = require("ojs/ojmutablearraydataprovider");
1010
import { MessageToastItem } from "oj-c/message-toast";
1111
import { InputSearchElement } from "ojs/ojinputsearch";
12-
import { useState, useEffect, useRef } from "preact/hooks";
12+
import { useState, useEffect, useRef, useContext } from "preact/hooks";
1313
import * as Questions from "text!./data/questions.json";
1414
import * as Answers from "text!./data/answers.json";
15+
import { initWebSocket } from "./websocket-interface";
16+
import { InitStomp, sendPrompt } from "./stomp-interface";
17+
import { Client } from "@stomp/stompjs";
18+
import { ConvoCtx } from "../app";
1519

1620
type ServiceTypes = "text" | "summary" | "sim";
21+
type BackendTypes = "java" | "python";
1722
type Chat = {
1823
id?: number;
1924
question?: string;
2025
answer?: string;
2126
loading?: string;
2227
};
28+
29+
const defaultServiceType: string = localStorage.getItem("service") || "text";
30+
const defaultBackendType: string = localStorage.getItem("backend") || "java";
31+
2332
const Content = () => {
33+
const conversationId = useContext(ConvoCtx);
2434
const [update, setUpdate] = useState<Array<object>>([]);
2535
const [busy, setBusy] = useState<boolean>(false);
26-
const [summaryResults, setSummaryResults] = useState<string | null>("");
36+
const [summaryResults, setSummaryResults] = useState<string>("");
37+
const [modelId, setModelId] = useState<string | null>(null);
2738
const [summaryPrompt, setSummaryPrompt] = useState<string>();
28-
const [serviceType, setServiceType] = useState<ServiceTypes>("summary");
39+
const [serviceType, setServiceType] = useState<ServiceTypes>(
40+
defaultServiceType as ServiceTypes
41+
);
42+
const [backendType, setBackendType] = useState<BackendTypes>(
43+
defaultBackendType as BackendTypes
44+
);
2945
const [settingsOpened, setSettingsOpened] = useState<boolean>(false);
3046
const question = useRef<string>();
3147
const chatData = useRef<Array<object>>([]);
3248
const socket = useRef<WebSocket>();
33-
const [connState, setConnState] = useState<string>("Disconnected");
49+
const [client, setClient] = useState<Client | null>(null);
3450

3551
const messagesDP = useRef(
3652
new MutableArrayDataProvider<MessageToastItem["summary"], MessageToastItem>(
@@ -39,77 +55,6 @@ const Content = () => {
3955
)
4056
);
4157

42-
const gateway = `ws://${window.location.hostname}:1986`;
43-
let sockTimer: any = null;
44-
45-
// setup the websocket connection
46-
const initWebSocket = () => {
47-
console.log("Trying to open a WebSocket connection...");
48-
socket.current = new WebSocket(gateway);
49-
socket.current.binaryType = "arraybuffer";
50-
socket.current.onopen = onOpen;
51-
socket.current.onerror = onError;
52-
socket.current.onclose = onClose;
53-
socket.current.onmessage = onMessage;
54-
};
55-
56-
// handle all messages coming from the websocket service
57-
const onMessage = (event: any) => {
58-
const msg = JSON.parse(event.data);
59-
60-
switch (msg.msgType) {
61-
// switch (Object.keys(msg)[0]) {
62-
case "message":
63-
console.log("message: ", msg.data);
64-
return msg.data;
65-
case "question":
66-
console.log("question: ", msg.data);
67-
return msg.data;
68-
case "summary":
69-
console.log("summary");
70-
setSummaryResults(msg.data);
71-
return;
72-
case "answer":
73-
console.log("answer: ", msg.data);
74-
if (msg.data !== "connected") {
75-
let tempArray = [...chatData.current];
76-
// remove the animation item before adding answer
77-
setBusy(false);
78-
tempArray.pop();
79-
messagesDP.current.data = [];
80-
tempArray.push({
81-
id: tempArray.length as number,
82-
answer: msg.data,
83-
});
84-
chatData.current = tempArray;
85-
setUpdate(chatData.current);
86-
}
87-
return msg.data;
88-
default:
89-
return "unknown";
90-
}
91-
};
92-
93-
const onOpen = () => {
94-
clearInterval(sockTimer);
95-
console.log("Connection opened");
96-
socket.current?.send(
97-
JSON.stringify({ msgType: "message", data: "connected" })
98-
);
99-
setConnState("Connected");
100-
};
101-
102-
// if the connection is lost, wait one minute and try again.
103-
const onError = () => {
104-
sockTimer = setInterval(initWebSocket, 1000 * 60);
105-
};
106-
function onClose() {
107-
console.log("Connection closed");
108-
setConnState("Disconnected");
109-
socket.current ? (socket.current.onclose = () => {}) : null;
110-
socket.current?.close();
111-
}
112-
11358
// Simulation code
11459
const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));
11560
const runSimulation = async () => {
@@ -121,7 +66,6 @@ const Content = () => {
12166
if (Q) {
12267
if (x > 0) tempArray.pop();
12368
tempArray.push({ question: JSON.parse(Questions)[x] });
124-
// tempArray.push({ loading: "loading" });
12569
Q = false;
12670
x++;
12771
} else {
@@ -135,24 +79,52 @@ const Content = () => {
13579
await sleep(2000);
13680
}
13781
};
82+
13883
useEffect(() => {
13984
switch (serviceType) {
14085
case "text":
141-
initWebSocket();
142-
console.log("Running Gen AI");
86+
if (backendType === "python") {
87+
initWebSocket(
88+
setSummaryResults,
89+
setBusy,
90+
setUpdate,
91+
messagesDP,
92+
socket,
93+
chatData
94+
);
95+
} else {
96+
setClient(
97+
InitStomp(setBusy, setUpdate, messagesDP, chatData, serviceType)
98+
);
99+
}
100+
console.log("Running Generative service");
143101
return;
144102
case "sim":
145103
runSimulation();
146-
console.log("running simulation");
104+
console.log("Running simulation");
147105
return;
148106
case "summary":
149-
initWebSocket();
150-
console.log("summary loading");
107+
if (backendType === "python") {
108+
initWebSocket(
109+
setSummaryResults,
110+
setBusy,
111+
setUpdate,
112+
messagesDP,
113+
socket,
114+
chatData
115+
);
116+
} else {
117+
setClient(
118+
InitStomp(setBusy, setUpdate, messagesDP, chatData, serviceType)
119+
);
120+
}
121+
console.log("Running Summarization service");
151122
return;
152123
}
153124
return () => {
154125
socket.current ? (socket.current.onclose = () => {}) : null;
155126
socket.current?.close();
127+
client?.deactivate();
156128
};
157129
}, [serviceType]);
158130

@@ -168,7 +140,6 @@ const Content = () => {
168140
autoTimeout: "on",
169141
},
170142
];
171-
//alert("Still waiting for an answer! Hang in there a little longer.");
172143
return;
173144
}
174145
if (event.detail.value) {
@@ -191,12 +162,13 @@ const Content = () => {
191162
setUpdate(chatData.current);
192163
setBusy(true);
193164

194-
// simulating the delay for now just to show what the animation looks like.
195-
setTimeout(() => {
165+
if (backendType === "python") {
196166
socket.current?.send(
197167
JSON.stringify({ msgType: "question", data: question.current })
198168
);
199-
}, 300);
169+
} else {
170+
sendPrompt(client, question.current!, modelId!, conversationId!);
171+
}
200172
}
201173
};
202174

@@ -215,19 +187,32 @@ const Content = () => {
215187
};
216188

217189
const serviceTypeChangeHandler = (service: ServiceTypes) => {
190+
localStorage.setItem("service", service);
218191
setUpdate([]);
219192
chatData.current = [];
220193
setServiceType(service);
221-
toggleDrawer();
222194
};
223-
195+
const backendTypeChangeHandler = (backend: BackendTypes) => {
196+
setUpdate([]);
197+
chatData.current = [];
198+
setBackendType(backend);
199+
localStorage.setItem("backend", backend);
200+
location.reload();
201+
};
202+
const modelIdChangeHandler = (event: CustomEvent) => {
203+
console.log("model Id: ", event.detail.value);
204+
if (event.detail.value != null) setModelId(event.detail.value);
205+
};
224206
const clearSummary = () => {
225207
setSummaryResults("");
226208
};
227209

228210
const updateSummaryPrompt = (val: string) => {
229211
setSummaryPrompt(val);
230212
};
213+
const updateSummaryResults = (summary: string) => {
214+
setSummaryResults(summary);
215+
};
231216

232217
return (
233218
<div class="oj-web-applayout-max-width oj-web-applayout-content oj-flex oj-sm-flex-direction-column demo-bg-main">
@@ -238,8 +223,11 @@ const Content = () => {
238223
aria-label="Settings Drawer"
239224
>
240225
<Settings
241-
serviceType={serviceType}
242-
serviceChange={serviceTypeChangeHandler}
226+
aiServiceType={serviceType}
227+
backendType={backendType}
228+
aiServiceChange={serviceTypeChangeHandler}
229+
backendChange={backendTypeChangeHandler}
230+
modelIdChange={modelIdChangeHandler}
243231
/>
244232
</oj-c-drawer-popup>
245233
<div class="oj-flex-bar oj-flex-item demo-header oj-sm-12">
@@ -248,9 +236,7 @@ const Content = () => {
248236
position="top"
249237
onojClose={handleToastClose}
250238
></oj-c-message-toast>
251-
{/* <h1 class="oj-typography-heading-lg oj-flex-bar-start"> </h1> */}
252239
<div class="oj-flex-bar-end oj-color-invert demo-header-end">
253-
{/* <h6 class="oj-sm-margin-2x-end">{connState}</h6> */}
254240
<oj-button onojAction={toggleDrawer} label="Toggle" display="icons">
255241
<span slot="startIcon" class="oj-ux-ico-menu"></span>
256242
</oj-button>
@@ -273,9 +259,11 @@ const Content = () => {
273259
{serviceType === "summary" && (
274260
<Summary
275261
fileChanged={handleFileUpload}
262+
summaryChanged={updateSummaryResults}
276263
summary={summaryResults}
277264
clear={clearSummary}
278265
prompt={updateSummaryPrompt}
266+
backendType={backendType}
279267
/>
280268
)}
281269
</div>

0 commit comments

Comments
 (0)