7db45447 by Janis

Merge branch '28859_integrate_llm_chatbot_plus' into 'master'

opensource

See merge request !81
2 parents 34d94fa0 7e30965a
...@@ -28,9 +28,12 @@ function App() { ...@@ -28,9 +28,12 @@ function App() {
28 const [chatLogTurbo, setChatLogTurbo] = useState(defaultChatLogTurbo); 28 const [chatLogTurbo, setChatLogTurbo] = useState(defaultChatLogTurbo);
29 // 29 //
30 30
31 const [chatLogOpenSource, setChatLogOpenSource] = useState([]);
32
31 function clearChat(){ 33 function clearChat(){
32 setChatLog([]); 34 setChatLog([]);
33 setChatLogTurbo(defaultChatLogTurbo); 35 setChatLogTurbo(defaultChatLogTurbo);
36 setChatLogOpenSource([]);
34 setChatInput(""); 37 setChatInput("");
35 setStartedInteraction(false); 38 setStartedInteraction(false);
36 } 39 }
...@@ -94,12 +97,20 @@ function App() { ...@@ -94,12 +97,20 @@ function App() {
94 setChatLog(prevChatLog => [...prevChatLog, userMessage]); 97 setChatLog(prevChatLog => [...prevChatLog, userMessage]);
95 98
96 var messages = chatLogNew.map((message) => { if(message.user !== 'me') return message.message }).join("\n") 99 var messages = chatLogNew.map((message) => { if(message.user !== 'me') return message.message }).join("\n")
97 if(currentModel == GPTTurbo || currentModel == GPTTurbo0301) { 100 if(currentModel === GPTTurbo || currentModel === GPTTurbo0301) {
98 // "gpt-3.5-turbo" 101 // "gpt-3.5-turbo"
99 let chatLogTurboNew = [...chatLogTurbo, { role: "user", content: chatInput }]; 102 let chatLogTurboNew = [...chatLogTurbo, { role: "user", content: chatInput }];
100 setChatLogTurbo(chatLogTurboNew); 103 setChatLogTurbo(chatLogTurboNew);
101 messages = JSON.stringify(chatLogTurboNew); 104 messages = JSON.stringify(chatLogTurboNew);
102 } 105 }
106
107 if(currentModel === "openchat_3.5-GPTQ" || currentModel === "zephyr-7B-beta-GPTQ") {
108 // "gpt-3.5-turbo"
109 let chatLogOpenSourceNew = [...chatLogOpenSource, { role: "user", content: chatInput }];
110 setChatLogOpenSource(chatLogOpenSourceNew);
111 messages = JSON.stringify(chatLogOpenSourceNew);
112 }
113
103 let intervalId = startInterval(); 114 let intervalId = startInterval();
104 try { 115 try {
105 const response = await fetch(process.env.REACT_APP_SERVER_URL + "/api", { 116 const response = await fetch(process.env.REACT_APP_SERVER_URL + "/api", {
...@@ -117,6 +128,7 @@ function App() { ...@@ -117,6 +128,7 @@ function App() {
117 const parsedData = data.message.trim(); 128 const parsedData = data.message.trim();
118 // "gpt-3.5-turbo" 129 // "gpt-3.5-turbo"
119 let chatLogTurboNew = chatLogTurbo; 130 let chatLogTurboNew = chatLogTurbo;
131 let chatLogOpenSourceNew = chatLogOpenSource;
120 if(data.success === false) { 132 if(data.success === false) {
121 setChatLog(prevChatLog => { 133 setChatLog(prevChatLog => {
122 const lastMsg = prevChatLog[prevChatLog.length - 2]; 134 const lastMsg = prevChatLog[prevChatLog.length - 2];
...@@ -129,7 +141,11 @@ function App() { ...@@ -129,7 +141,11 @@ function App() {
129 } 141 }
130 chatLogTurboNew.push({ role: "user", content: userModifiedInput }); 142 chatLogTurboNew.push({ role: "user", content: userModifiedInput });
131 chatLogTurboNew.push({ role: "assistant", content: parsedData }); 143 chatLogTurboNew.push({ role: "assistant", content: parsedData });
144
145 chatLogOpenSourceNew.push({ role: "user", content: userModifiedInput });
146 chatLogOpenSourceNew.push({ role: "assistant", content: parsedData });
132 setChatLogTurbo(chatLogTurboNew); 147 setChatLogTurbo(chatLogTurboNew);
148 setChatLogOpenSource(chatLogOpenSourceNew);
133 // 149 //
134 clearInterval(intervalId); 150 clearInterval(intervalId);
135 const programmingKeywords = ['code', 'application', 'controller', 'rails' , 'PHP', 'java', 'javascript', 'script', 'console', 'python', 'programming', 'table']; 151 const programmingKeywords = ['code', 'application', 'controller', 'rails' , 'PHP', 'java', 'javascript', 'script', 'console', 'python', 'programming', 'table'];
......
...@@ -33,7 +33,7 @@ const SideMenu = ({ ...@@ -33,7 +33,7 @@ const SideMenu = ({
33 {models && models.length ? ( 33 {models && models.length ? (
34 models.map((model, index) => ( 34 models.map((model, index) => (
35 <option key={model.id} value={model.id}> 35 <option key={model.id} value={model.id}>
36 {model.id} 36 {model.id} {model.beta ? "(beta)" : ""}
37 </option> 37 </option>
38 )) 38 ))
39 ) : ( 39 ) : (
......
1 OPENAI_API_ORG= 1 OPENAI_API_ORG=
2 OPENAI_API_KEY= 2 OPENAI_API_KEY=
3
4
5 OPENSOURCE_MODELS="openchat_3.5-GPTQ,zephyr-7B-beta-GPTQ"
6 OPENSOURCE_ENDPOINTS={"openchat_3.5-GPTQ": "https://openchat.llm.ai-pro.org/v1", "zephyr-7B-beta-GPTQ": "https://zephyr.llm.ai-pro.org/v1"}
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -75,8 +75,13 @@ app.use(rateLimiter) ...@@ -75,8 +75,13 @@ app.use(rateLimiter)
75 app.post('/api', async (req, res) => { 75 app.post('/api', async (req, res) => {
76 const { message, currentModel, temperature } = req.body; 76 const { message, currentModel, temperature } = req.body;
77 77
78 if(currentModel == "gpt-3.5-turbo" || currentModel == "gpt-3.5-turbo-0301") { 78 if (currentModel == "gpt-3.5-turbo" || currentModel == "gpt-3.5-turbo-0301") {
79 runGPTTurbo(req,res); 79 runGPTTurbo(req, res);
80 return;
81 }
82
83 if (currentModel == "openchat_3.5-GPTQ" || currentModel == "zephyr-7B-beta-GPTQ") {
84 runOpensource(req, res);
80 return; 85 return;
81 } 86 }
82 87
...@@ -87,10 +92,10 @@ app.post('/api', async (req, res) => { ...@@ -87,10 +92,10 @@ app.post('/api', async (req, res) => {
87 } 92 }
88 let query_prompt = `${greetingPrompt}\n${message}`; 93 let query_prompt = `${greetingPrompt}\n${message}`;
89 str_length = req.body.message.split(' ').length; 94 str_length = req.body.message.split(' ').length;
90 if (str_length>=800){ 95 if (str_length >= 800) {
91 arr_body = req.body.message.split("\n"); 96 arr_body = req.body.message.split("\n");
92 if (arr_body.length>=4){ 97 if (arr_body.length >= 4) {
93 var i = arr_body.length-2 98 var i = arr_body.length - 2
94 while (i--) { 99 while (i--) {
95 arr_body.splice(i, 1); 100 arr_body.splice(i, 1);
96 } 101 }
...@@ -101,7 +106,7 @@ app.post('/api', async (req, res) => { ...@@ -101,7 +106,7 @@ app.post('/api', async (req, res) => {
101 input: query_prompt 106 input: query_prompt
102 }, { headers: { 'content-type': 'application/json', 'Authorization': `Bearer ${process.env.OPENAI_API_KEY}` } }); 107 }, { headers: { 'content-type': 'application/json', 'Authorization': `Bearer ${process.env.OPENAI_API_KEY}` } });
103 108
104 if(moderation.data.results[0].flagged) { 109 if (moderation.data.results[0].flagged) {
105 res.json({ 110 res.json({
106 success: false, 111 success: false,
107 message: "I'm sorry, but I can't assist with that. We want everyone to use our tool safely and responsibly.\nIf you have any other questions or need advice on a different topic, feel free to ask." 112 message: "I'm sorry, but I can't assist with that. We want everyone to use our tool safely and responsibly.\nIf you have any other questions or need advice on a different topic, feel free to ask."
...@@ -142,11 +147,11 @@ app.post('/api', async (req, res) => { ...@@ -142,11 +147,11 @@ app.post('/api', async (req, res) => {
142 }) 147 })
143 } catch (e) { 148 } catch (e) {
144 let error_msg = e.response.data.error.message ? e.response.data.error.message : ''; 149 let error_msg = e.response.data.error.message ? e.response.data.error.message : '';
145 if (error_msg.indexOf('maximum context length')>=0){ 150 if (error_msg.indexOf('maximum context length') >= 0) {
146 res.json({ 151 res.json({
147 message: "The output for your prompt is too long for us to process. Please reduce your prompt and try again.", 152 message: "The output for your prompt is too long for us to process. Please reduce your prompt and try again.",
148 }) 153 })
149 }else{ 154 } else {
150 console.log(e.response); 155 console.log(e.response);
151 } 156 }
152 } finally { 157 } finally {
...@@ -164,7 +169,7 @@ async function runGPTTurbo(req, res) { ...@@ -164,7 +169,7 @@ async function runGPTTurbo(req, res) {
164 input: query_prompt 169 input: query_prompt
165 }, { headers: { 'content-type': 'application/json', 'Authorization': `Bearer ${process.env.OPENAI_API_KEY}` } }); 170 }, { headers: { 'content-type': 'application/json', 'Authorization': `Bearer ${process.env.OPENAI_API_KEY}` } });
166 171
167 if(moderation.data.results[0].flagged) { 172 if (moderation.data.results[0].flagged) {
168 res.json({ 173 res.json({
169 success: false, 174 success: false,
170 message: "I'm sorry, but I can't assist with that. We want everyone to use our tool safely and responsibly.\nIf you have any other questions or need advice on a different topic, feel free to ask." 175 message: "I'm sorry, but I can't assist with that. We want everyone to use our tool safely and responsibly.\nIf you have any other questions or need advice on a different topic, feel free to ask."
...@@ -182,9 +187,9 @@ async function runGPTTurbo(req, res) { ...@@ -182,9 +187,9 @@ async function runGPTTurbo(req, res) {
182 input = response.data.choices[0].message.content 187 input = response.data.choices[0].message.content
183 } catch (e) { 188 } catch (e) {
184 let error_msg = e.response.data.error.message ? e.response.data.error.message : ''; 189 let error_msg = e.response.data.error.message ? e.response.data.error.message : '';
185 if (error_msg.indexOf('maximum context length')>=0){ 190 if (error_msg.indexOf('maximum context length') >= 0) {
186 input = "The output for your prompt is too long for us to process. Please reduce your prompt and try again."; 191 input = "The output for your prompt is too long for us to process. Please reduce your prompt and try again.";
187 }else{ 192 } else {
188 console.log(e.response); 193 console.log(e.response);
189 } 194 }
190 } finally { 195 } finally {
...@@ -216,11 +221,84 @@ async function runGPTTurbo(req, res) { ...@@ -216,11 +221,84 @@ async function runGPTTurbo(req, res) {
216 } 221 }
217 } 222 }
218 223
224 const get_endpoint_api_url = (currentModel) => {
225 const OPENSOURCE_ENDPOINTS = process.env.OPENSOURCE_ENDPOINTS;
226 const endpoints = JSON.parse(OPENSOURCE_ENDPOINTS);
227 const endpoint_api_url = endpoints?.[currentModel];
228 return endpoint_api_url
229 }
230 async function runOpensource(req, res) {
231 const { message, currentModel, temperature } = req.body;
232 var input = '';
233 const message_history = JSON.parse(message);
234 const query_prompt = message_history.length ? message_history[message_history.length - 1].content : "";
235
236 try {
237 const endpoint_api_url = get_endpoint_api_url(currentModel);
238 console.log('endpoint_api_url', endpoint_api_url);
239 const response = await axios.post(endpoint_api_url + '/chat/completions', {
240 messages: JSON.parse(message),
241 temperature
242 }, {
243 headers: {
244 'Content-Type': 'application/json',
245 // 'Authorization': `Bearer ${process.env.OPENSOURCE_API_KEY}`
246 },
247 });
248 console.log(" zephyr response", response.data.choices[0])
249 input = response.data.choices[0].message.content
250 } catch (e) {
251 let error_msg = e.response.data.error.message ? e.response.data.error.message : '';
252 if (error_msg.indexOf('maximum context length') >= 0) {
253 input = "The output for your prompt is too long for us to process. Please reduce your prompt and try again.";
254 } else {
255 console.log(e.response);
256 }
257 } finally {
258
259 let usage = {};
260 let enc = null;
261 try {
262 enc = encodingForModel('gpt-3.5-turbo');
263 usage.prompt_tokens = (enc.encode(query_prompt)).length;
264 usage.completion_tokens = (enc.encode(input)).length;
265 usage.total_tokens = usage.prompt_tokens + usage.completion_tokens;
266 } catch (e) {
267 console.log('Error encoding prompt text', e);
268 }
269
270 res.json({
271 prompt: JSON.parse(message),
272 usage: usage,
273 message: anchorme({
274 input,
275 options: {
276 attributes: {
277 target: "_blank"
278 },
279 }
280 })
281 });
282 return;
283 }
284 }
285
286
287
219 // Get Models Route 288 // Get Models Route
220 app.get('/models', async (req, res) => { 289 app.get('/models', async (req, res) => {
221 const response = await openai.listEngines(); 290 const response = await openai.listEngines();
291 const models = response.data;
292 const opensource_models = process.env.OPENSOURCE_MODELS ? process.env.OPENSOURCE_MODELS.split(',') : [];
293 opensource_models.forEach((model) => {
294 models.data.push({
295 id: model,
296 beta: true,
297 });
298 })
299
222 res.json({ 300 res.json({
223 models: response.data 301 models
224 }) 302 })
225 }); 303 });
226 304
......
...@@ -10,11 +10,15 @@ ...@@ -10,11 +10,15 @@
10 "license": "ISC", 10 "license": "ISC",
11 "dependencies": { 11 "dependencies": {
12 "anchorme": "^2.1.2", 12 "anchorme": "^2.1.2",
13 "axios": "^1.5.1",
13 "body-parser": "^1.20.1", 14 "body-parser": "^1.20.1",
15 "cookie": "0.5.0",
16 "cookie-parser": "1.4.6",
14 "cors": "^2.8.5", 17 "cors": "^2.8.5",
15 "dotenv": "^16.0.3", 18 "dotenv": "^16.0.3",
16 "express": "^4.18.2", 19 "express": "^4.18.2",
17 "express-rate-limit": "^6.7.0", 20 "express-rate-limit": "^6.7.0",
21 "js-tiktoken": "1.0.7",
18 "morgan": "^1.10.0", 22 "morgan": "^1.10.0",
19 "openai": "^3.2.0" 23 "openai": "^3.2.0"
20 } 24 }
...@@ -47,13 +51,34 @@ ...@@ -47,13 +51,34 @@
47 "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" 51 "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
48 }, 52 },
49 "node_modules/axios": { 53 "node_modules/axios": {
50 "version": "0.26.1", 54 "version": "1.6.2",
51 "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", 55 "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz",
52 "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", 56 "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==",
53 "dependencies": { 57 "dependencies": {
54 "follow-redirects": "^1.14.8" 58 "follow-redirects": "^1.15.0",
59 "form-data": "^4.0.0",
60 "proxy-from-env": "^1.1.0"
55 } 61 }
56 }, 62 },
63 "node_modules/base64-js": {
64 "version": "1.5.1",
65 "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
66 "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
67 "funding": [
68 {
69 "type": "github",
70 "url": "https://github.com/sponsors/feross"
71 },
72 {
73 "type": "patreon",
74 "url": "https://www.patreon.com/feross"
75 },
76 {
77 "type": "consulting",
78 "url": "https://feross.org/support"
79 }
80 ]
81 },
57 "node_modules/basic-auth": { 82 "node_modules/basic-auth": {
58 "version": "2.0.1", 83 "version": "2.0.1",
59 "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", 84 "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz",
...@@ -151,6 +176,26 @@ ...@@ -151,6 +176,26 @@
151 "node": ">= 0.6" 176 "node": ">= 0.6"
152 } 177 }
153 }, 178 },
179 "node_modules/cookie-parser": {
180 "version": "1.4.6",
181 "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz",
182 "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==",
183 "dependencies": {
184 "cookie": "0.4.1",
185 "cookie-signature": "1.0.6"
186 },
187 "engines": {
188 "node": ">= 0.8.0"
189 }
190 },
191 "node_modules/cookie-parser/node_modules/cookie": {
192 "version": "0.4.1",
193 "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
194 "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==",
195 "engines": {
196 "node": ">= 0.6"
197 }
198 },
154 "node_modules/cookie-signature": { 199 "node_modules/cookie-signature": {
155 "version": "1.0.6", 200 "version": "1.0.6",
156 "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 201 "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
...@@ -431,6 +476,14 @@ ...@@ -431,6 +476,14 @@
431 "node": ">= 0.10" 476 "node": ">= 0.10"
432 } 477 }
433 }, 478 },
479 "node_modules/js-tiktoken": {
480 "version": "1.0.7",
481 "resolved": "https://registry.npmjs.org/js-tiktoken/-/js-tiktoken-1.0.7.tgz",
482 "integrity": "sha512-biba8u/clw7iesNEWLOLwrNGoBP2lA+hTaBLs/D45pJdUPFXyxD6nhcDVtADChghv4GgyAiMKYMiRx7x6h7Biw==",
483 "dependencies": {
484 "base64-js": "^1.5.1"
485 }
486 },
434 "node_modules/media-typer": { 487 "node_modules/media-typer": {
435 "version": "0.3.0", 488 "version": "0.3.0",
436 "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 489 "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
...@@ -565,6 +618,14 @@ ...@@ -565,6 +618,14 @@
565 "form-data": "^4.0.0" 618 "form-data": "^4.0.0"
566 } 619 }
567 }, 620 },
621 "node_modules/openai/node_modules/axios": {
622 "version": "0.26.1",
623 "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz",
624 "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
625 "dependencies": {
626 "follow-redirects": "^1.14.8"
627 }
628 },
568 "node_modules/parseurl": { 629 "node_modules/parseurl": {
569 "version": "1.3.3", 630 "version": "1.3.3",
570 "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 631 "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
...@@ -590,6 +651,11 @@ ...@@ -590,6 +651,11 @@
590 "node": ">= 0.10" 651 "node": ">= 0.10"
591 } 652 }
592 }, 653 },
654 "node_modules/proxy-from-env": {
655 "version": "1.1.0",
656 "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
657 "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
658 },
593 "node_modules/qs": { 659 "node_modules/qs": {
594 "version": "6.11.0", 660 "version": "6.11.0",
595 "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", 661 "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!