diff --git a/.gitignore b/.gitignore index 2e924c5..78d1d05 100644 --- a/.gitignore +++ b/.gitignore @@ -130,3 +130,4 @@ dist .pnp.* models +zuliprc diff --git a/config/install.sh b/config/install.sh new file mode 100644 index 0000000..c886821 --- /dev/null +++ b/config/install.sh @@ -0,0 +1 @@ +wget 'https://cdn-lfs.huggingface.co/repos/7c/00/7c0031e9b422425e0764b943d87f4b7915edcd162b55b2538673504ea487c544/9c1bb4808f40aa0059d5343d3aac05fb75d368c240b664878d53d16bf27ade2b?response-content-disposition=attachment%3B+filename*%3DUTF-8%27%27ggml-alpaca-7b-q4.bin%3B+filename%3D%22ggml-alpaca-7b-q4.bin%22%3B&response-content-type=application%2Foctet-stream&Expires=1683931860&Policy=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cHM6Ly9jZG4tbGZzLmh1Z2dpbmdmYWNlLmNvL3JlcG9zLzdjLzAwLzdjMDAzMWU5YjQyMjQyNWUwNzY0Yjk0M2Q4N2Y0Yjc5MTVlZGNkMTYyYjU1YjI1Mzg2NzM1MDRlYTQ4N2M1NDQvOWMxYmI0ODA4ZjQwYWEwMDU5ZDUzNDNkM2FhYzA1ZmI3NWQzNjhjMjQwYjY2NDg3OGQ1M2QxNmJmMjdhZGUyYj9yZXNwb25zZS1jb250ZW50LWRpc3Bvc2l0aW9uPSomcmVzcG9uc2UtY29udGVudC10eXBlPSoiLCJDb25kaXRpb24iOnsiRGF0ZUxlc3NUaGFuIjp7IkFXUzpFcG9jaFRpbWUiOjE2ODM5MzE4NjB9fX1dfQ__&Signature=SNJophMJ6KfdGjM0trRBotydeitN-Q-z2BwzrqIuNmW5p51eUGaJjDlG25fs0L323zGwszeamLFZaRLlb3N5HtHYAynPtyxIAksMl4vJkoQa%7E%7Ed1OBiat0nSfHFR-avdETicOrK75ATQPdy4iOX0Y9kyQjHOnf0bSzU32ABS%7EwMypn5xrnHIQ69del2lBwOXvKzxrrMAr2bgWWzLw4NjdZv9l8EUXy5lEXCmiPmzNJaiY4CsV4cB6iA1J21e4yZiw8KjpH6W0OxVG2i1A9ttGquTLIeoi4wRbPAhP-cZEuqIutaElcgeoMkYnwwTYvJ3CdtBjkPLtGxxfgZruuETYQ__&Key-Pair-Id=KVTP0A1DKRTAX' diff --git a/llama.js b/llama.js index 7bb9725..a920adb 100644 --- a/llama.js +++ b/llama.js @@ -1,10 +1,7 @@ import { LLM } from "llama-node"; import { LLamaCpp } from "llama-node/dist/llm/llama-cpp.js"; import path from "path"; -const model = path.resolve( - process.cwd(), - "./models/ggml-alpaca-7b-q4.bin" -); +const model = path.resolve(process.cwd(), "./models/ggml-alpaca-7b-q4.bin"); const llama = new LLM(LLamaCpp); const config = { path: model, @@ -20,26 +17,34 @@ const config = { useMmap: true, }; -const prompt = ( - question -) => `Answer as an assistant. +const prompt = (question) => `Answer as an assistant. USER: (asks a question) ${question} ASSISTANT: `; export function init() { + console.log(config); return llama.load(config); } -export const askllama = (question, cb) => { - const params = { - nThreads: 10, - nTokPredict: 2048, - topK: 40, - topP: 0.1, - temp: 0.2, - repeatPenalty: 1, - prompt: prompt(question), - }; - console.log(params); - return llama.createCompletion(params, Function.prototype); +export const llamaParams = (question) => ({ + nThreads: 10, + nTokPredict: 2048, + topK: 40, + topP: 0.1, + temp: 0.2, + repeatPenalty: 1, + prompt: prompt(question), +}); + +export const askllama = async ({ question, params, cb }) => { + const { tokens } = await llama.createCompletion( + params || llamaParams(question), + cb || Function.prototype + ); + const responseString = tokens.filter((t) => t !== "\n\n\n").join(""); + const responseWithoutExtraDialog = responseString.slice( + 0, + responseString.indexOf("USER") + ); + return responseWithoutExtraDialog; }; diff --git a/package.json b/package.json index 9b79186..4d01658 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "@llama-node/core": "^0.1.0", "@llama-node/llama-cpp": "^0.1.0", "express": "^4.18.2", - "llama-node": "^0.1.0" + "llama-node": "^0.1.0", + "zulip-js": "^2.0.9" } } diff --git a/server.js b/server.js index 0a82fb4..7b2ccf7 100644 --- a/server.js +++ b/server.js @@ -1,7 +1,7 @@ import { createServer } from "http"; import express from "express"; import bodyParser from "body-parser"; -import { askllama, init } from "./llama.js"; +import { askllama, init, llamaParams } from "./llama.js"; const app = express(); const server = createServer(app); @@ -10,13 +10,12 @@ const port = process.env.PORT || 8000; app.use(bodyParser.urlencoded({ extended: false })); app.use(express.json()); -app.post("/llamaChat", async (req, res) => { +app.post("/chat", async (req, res) => { const { message } = req.body; - const { tokens } = await askllama(message); - console.log(tokens); - const responseString = tokens.filter((t) => t !== "\n\n\n").join(""); - const response = responseString.slice(0, responseString.indexOf("USER")); + console.log(`Request: ${message}`); + const response = await askllama({ question: message }); + console.log("Finished"); res.json({ response, }); @@ -25,5 +24,6 @@ app.post("/llamaChat", async (req, res) => { init().then(() => server.listen(port, () => { console.log(`application is running at: http://localhost:${port}`); + console.log("Using llama params:\n", llamaParams()); }) ); diff --git a/yarn.lock b/yarn.lock index a66c00a..985f901 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,13 @@ # yarn lockfile v1 +"@babel/runtime@^7.12.5": + version "7.21.5" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.5.tgz#8492dddda9644ae3bda3b45eabe87382caee7200" + integrity sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q== + dependencies: + regenerator-runtime "^0.13.11" + "@llama-node/cli@0.1.0": version "0.1.0" resolved "https://registry.yarnpkg.com/@llama-node/cli/-/cli-0.1.0.tgz#40ba4cb39be930e90f726c800f22111d080f44f5" @@ -50,6 +57,11 @@ array-flatten@1.1.1: resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + body-parser@1.20.1: version "1.20.1" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" @@ -102,6 +114,13 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +combined-stream@^1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + content-disposition@0.5.4: version "0.5.4" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" @@ -131,6 +150,11 @@ debug@2.6.9: dependencies: ms "2.0.0" +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + depd@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" @@ -221,6 +245,15 @@ finalhandler@1.2.0: statuses "2.0.1" unpipe "~1.0.0" +form-data@^2.3.2: + version "2.5.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4" + integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + forwarded@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" @@ -285,6 +318,11 @@ inherits@2.0.4: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +ini@^1.3.7: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + ipaddr.js@1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" @@ -295,6 +333,21 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== +isomorphic-fetch@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz#0267b005049046d2421207215d45d6a262b8b8b4" + integrity sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA== + dependencies: + node-fetch "^2.6.1" + whatwg-fetch "^3.4.1" + +isomorphic-form-data@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isomorphic-form-data/-/isomorphic-form-data-2.0.0.tgz#9f6adf1c4c61ae3aefd8f110ab60fb9b143d6cec" + integrity sha512-TYgVnXWeESVmQSg4GLVbalmQ+B4NPi/H4eWxqALKj63KsUrcu301YDjBqaOw3h+cbak7Na4Xyps3BiptHtxTfg== + dependencies: + form-data "^2.3.2" + llama-node@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/llama-node/-/llama-node-0.1.0.tgz#016c87da3fcde2bd523ed451810d41f900559b33" @@ -326,7 +379,7 @@ mime-db@1.52.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-types@~2.1.24, mime-types@~2.1.34: +mime-types@^2.1.12, mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== @@ -353,6 +406,13 @@ negotiator@0.6.3: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== +node-fetch@^2.6.1: + version "2.6.11" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.11.tgz#cde7fc71deef3131ef80a738919f999e6edfff25" + integrity sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w== + dependencies: + whatwg-url "^5.0.0" + object-inspect@^1.9.0: version "1.12.3" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" @@ -405,6 +465,11 @@ raw-body@2.5.1: iconv-lite "0.4.24" unpipe "1.0.0" +regenerator-runtime@^0.13.11: + version "0.13.11" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" + integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== + require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -489,6 +554,11 @@ toidentifier@1.0.1: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + type-is@~1.6.18: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" @@ -512,6 +582,24 @@ vary@~1.1.2: resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +whatwg-fetch@^3.4.1: + version "3.6.2" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c" + integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" @@ -543,3 +631,13 @@ yargs@^17.7.1: string-width "^4.2.3" y18n "^5.0.5" yargs-parser "^21.1.1" + +zulip-js@^2.0.9: + version "2.0.9" + resolved "https://registry.yarnpkg.com/zulip-js/-/zulip-js-2.0.9.tgz#3708d2dd7cd31ca756c5701a69152bb95836abad" + integrity sha512-I8Cjnxa7qTaHwxN6YZ4IOL2IiTz89rD4NZul1t8Hzu+q8muSE4LT2iVAlnCrCut4KEbOZDA+Bsgp0/CtFkUbnA== + dependencies: + "@babel/runtime" "^7.12.5" + ini "^1.3.7" + isomorphic-fetch "^3.0.0" + isomorphic-form-data "2.0.0" diff --git a/zulipBot.js b/zulipBot.js new file mode 100644 index 0000000..76a2960 --- /dev/null +++ b/zulipBot.js @@ -0,0 +1,38 @@ +import zulipInit from "zulip-js"; +import { askllama, init, llamaParams } from "./llama.js"; + +const config = { zuliprc: "./zuliprc" }; +const client = await zulipInit(config); + +async function main() { + let { queue_id, last_event_id } = await client.queues.register({ + event_types: ["message"], + }); + + await init(); + + while (42) { + const { events } = await client.events.retrieve({ + queue_id, + last_event_id, + }); + + events.forEach(async (event) => { + last_event_id = Math.max(last_event_id, Number(event.id)); + const isMentioned = event.flags?.includes("mentioned"); + console.log(event.message); + if (isMentioned && event.type === "message") { + const content = await askllama({ question: event.message.content }); + await client.messages.send({ + to: event.message.sender_email, + type: "private", + //type: 'stream', + subject: "Testing gptBot", + content, + }); + } + }); + } +} + +main();