[{"data":1,"prerenderedAt":338},["ShallowReactive",2],{"blog-\u002Fblog\u002F2023\u002F05\u002Fchatgpt-nodered-fcn-node":3},{"id":4,"title":5,"body":6,"description":319,"extension":320,"meta":321,"navigation":333,"path":334,"seo":335,"stem":336,"__hash__":337},"blog\u002Fblog\u002F2023\u002F05\u002Fchatgpt-nodered-fcn-node.md","Chat GPT in Node-RED Function Nodes",{"type":7,"value":8,"toc":314},"minimark",[9,32,37,57,72,75,78,136,143,146,200,203,209,217,221,228,266,270,278,281,301,310],[10,11,12,13,20,21,26,27,31],"p",{},"Recently we ",[14,15,19],"a",{"href":16,"rel":17},"https:\u002F\u002Fwww.linkedin.com\u002Fposts\u002Fflowforge_chatgpt-with-node-red-function-nodes-activity-7052725869684953088-2yOA?utm_source=share&utm_medium=member_desktop",[18],"nofollow","posted a demo of ChatGPT integration in a Node-RED function node","\nonto our social media accounts. We have now ",[14,22,25],{"href":23,"target":24},"https:\u002F\u002Fgithub.com\u002FFlowFuse\u002Fnode-red-function-gpt","_blank","open-sourced"," this for all to play with, and ",[28,29,30],"strong",{},"welcome any and all contributions",".",[33,34,36],"h2",{"id":35},"how-it-works-prompt-engineering","How it Works - Prompt Engineering",[10,38,39,40,45,46,51,52,56],{},"OpenAI make a collection of their ",[14,41,44],{"href":42,"rel":43},"https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fmodels",[18],"Generative AI models"," available\nvia an API. We are wrapping OpenAI's ",[14,47,50],{"href":48,"rel":49},"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fopenai",[18],"node.js module",", and in particular\nusing the ",[53,54,55],"code",{},"openai.createChatCompletion()"," functionality. For this API, you provide a chat history, and ChatGPT will\nrespond with the next entry in that conversation.",[10,58,59,60,64,65,68,69,31],{},"In order to \"train\" ChatGPT for our use case of populating Node-RED function nodes, we first tried a collection of prompts, defining specific\nrequirements for the contents, e.g. ",[61,62,63],"em",{},"\"Always write Javascript\"",", ",[61,66,67],{},"\"Never include the wrapping function definition\"",",\n",[61,70,71],{},"\"Assume the input is always msg\"",[10,73,74],{},"It turns out though, that we were over-engineering it, we were not getting reliable results and ended up\nrealising that ChatGPT's existing knowledge of Node-RED was sufficient such that we could use that as a prompt:",[10,76,77],{},"Here's what we settled on:",[79,80,85],"pre",{"className":81,"code":82,"language":83,"meta":84,"style":84},"language-javascript shiki shiki-themes github-light github-dark","messages: [\n    {role: \"system\", content: \"always respond with content for a Node-RED function node, and don't add any commentary, always use const or let instead of var. Always return msg, unless told otherwise.\"},\n    {role: \"user\", content: prompt}\n],\n","javascript","",[53,86,87,100,119,130],{"__ignoreMap":84},[88,89,92,96],"span",{"class":90,"line":91},"line",1,[88,93,95],{"class":94},"sScJk","messages",[88,97,99],{"class":98},"sVt8B",": [\n",[88,101,103,106,110,113,116],{"class":90,"line":102},2,[88,104,105],{"class":98},"    {role: ",[88,107,109],{"class":108},"sZZnC","\"system\"",[88,111,112],{"class":98},", content: ",[88,114,115],{"class":108},"\"always respond with content for a Node-RED function node, and don't add any commentary, always use const or let instead of var. Always return msg, unless told otherwise.\"",[88,117,118],{"class":98},"},\n",[88,120,122,124,127],{"class":90,"line":121},3,[88,123,105],{"class":98},[88,125,126],{"class":108},"\"user\"",[88,128,129],{"class":98},", content: prompt}\n",[88,131,133],{"class":90,"line":132},4,[88,134,135],{"class":98},"],\n",[10,137,138,139,142],{},"Here we send a ",[53,140,141],{},"system"," prompt in order to setup ChatGPT, and then follow that immediately with whatever the user has typed.\nFrom our (limited) testing, this has given us fairly reliable results.",[10,144,145],{},"Breaking this prompt down:",[147,148,149,170,178,186],"ul",{},[150,151,152,157,158,161,162,165,166,169],"li",{},[61,153,154],{},[28,155,156],{},"\"Always respond with content for a Node-RED function node\"",": Ensured no surrounding ",[53,159,160],{},"function () {}"," definition and set expectations that the function would deal with a ",[53,163,164],{},"msg"," and likely ",[53,167,168],{},"msg.payload"," object.",[150,171,172,177],{},[61,173,174],{},[28,175,176],{},"\"Don't add any commentary\"",": ChatGPT likes to, well, chat. It would always return raw text justifying decisions, etc. Here, we just wanted the code.",[150,179,180,185],{},[61,181,182],{},[28,183,184],{},"\"Always use const or let instead of var\"",": This was Steve being picky.",[150,187,188,193,194,196,197,199],{},[61,189,190],{},[28,191,192],{},"\"Always return msg, unless told otherwise\"",": We found this wasn't mostly required, but occasionally it would try to return a different variable, and we'd lose context of ",[53,195,168],{},", or other data stored in ",[53,198,164],{},". So this just made sure we had the consistency.",[10,201,202],{},"The response from this API call is then populated into the contents of the active tab in the function node:",[204,205],"img",{"width":206,"alt":207,"src":208},1728,"Screenshot 2023-04-21 at 16 08 47","https:\u002F\u002Fuser-images.githubusercontent.com\u002F99246719\u002F233671631-fefa36c1-6db4-4392-a057-314c16fd91b7.png",[10,210,211,212,31],{},"In order to use it yourself, you will need a ",[14,213,216],{"href":214,"rel":215},"https:\u002F\u002Fplatform.openai.com\u002Faccount\u002Fapi-keys",[18],"valid API Key from OpenAI",[33,218,220],{"id":219},"additional-features","Additional Features",[10,222,223,224,227],{},"This was built in about a day by Steve and Joe, and we had plenty of ideas on what we'd like to add to it. We've\n",[14,225,25],{"href":23,"rel":226},[18]," it, and will add these as issues to the repo, but if anyone want so take a stab at contributing - that'd be most welcome!",[147,229,230,246,256],{},[150,231,232,241,242,245],{},[28,233,234,235,240],{},"Insert at Cursor (",[14,236,239],{"href":237,"rel":238},"https:\u002F\u002Fgithub.com\u002FFlowFuse\u002Fnode-red-function-gpt\u002Fissues\u002F11",[18],"issue","):"," Currently, the Ask GPT call will replace ",[61,243,244],{},"all"," of the content of that tab. Would be great\nto have the code insert wherever the cursor last was in order to add to existing code.",[150,247,248,255],{},[28,249,250,251,240],{},"Retain Conversation History (",[14,252,239],{"href":253,"rel":254},"https:\u002F\u002Fgithub.com\u002FFlowFuse\u002Fnode-red-function-gpt\u002Fissues\u002F12",[18]," Each time a new prompt is provided by the Node-RED user, we send a fresh conversation to OpenAI,\nmeaning that knowledge of previously asked questions are not retained.",[150,257,258,265],{},[28,259,260,261,240],{},"Client side ChatGPT Config (",[14,262,239],{"href":263,"rel":264},"https:\u002F\u002Fgithub.com\u002FFlowFuse\u002Fnode-red-function-gpt\u002Fissues\u002F13",[18]," Currently, when you add a new \"function-gpt\" node you need to select the ChatGTP\nConfig node and click \"Deploy\" before you can ask it a question. Our ChatGPT interaction operates server-side (to\nprotect your API key), so Node-RED needs that in the runtime first, before a call to ChatGPT can be made. Ideally,\nwe'd be smarter here and pass client-side creds along with the call such that we can use any changes made by the\nuser at the time of the call.",[33,267,269],{"id":268},"flowfuse-assistant-no-api-keys-required","FlowFuse Assistant - No API Keys Required!",[10,271,272,273,277],{},"Great news! You no longer need to manage OpenAI API keys or configure ChatGPT nodes. The ",[14,274,276],{"href":275},"\u002Fdocs\u002Fuser\u002Fexpert\u002F","FlowFuse Assistant"," is now built directly into Node-RED on FlowFuse Cloud, making AI-powered development even easier.",[10,279,280],{},"Available on FlowFuse Cloud, the Assistant offers:",[147,282,283,289,295],{},[150,284,285,288],{},[28,286,287],{},"Quick Function Node Creation",": Add function nodes to your flow without dragging from the palette",[150,290,291,294],{},[28,292,293],{},"In-line Code Generation",": Generate JavaScript code for function nodes, JSON for JSON editors, and Vue.js for FlowFuse Dashboard ui-template widgets",[150,296,297,300],{},[28,298,299],{},"Flow Explainer",": Select nodes and click \"Explain Flows\" to understand what they do",[10,302,303,304,309],{},"FlowFuse Assistant helps developers work faster and smarter with Node-RED. ",[14,305,308],{"href":306,"rel":307},"https:\u002F\u002Fapp.flowfuse.com\u002Faccount\u002Fcreate",[18],"Start your free trial"," to experience AI-powered Node-RED development on FlowFuse Cloud.",[311,312,313],"style",{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":84,"searchDepth":102,"depth":102,"links":315},[316,317,318],{"id":35,"depth":102,"text":36},{"id":219,"depth":102,"text":220},{"id":268,"depth":102,"text":269},"Recently we posted a demo of ChatGPT integration in a Node-RED function node\nonto our social media accounts. We have now open-sourced this for all to play with, and welcome any and all contributions.","md",{"navTitle":5,"excerpt":322},{"type":7,"value":323},[324],[10,325,12,326,20,329,26,331,31],{},[14,327,19],{"href":16,"rel":328},[18],[14,330,25],{"href":23,"target":24},[28,332,30],{},true,"\u002Fblog\u002F2023\u002F05\u002Fchatgpt-nodered-fcn-node",{"title":5,"description":319},"blog\u002F2023\u002F05\u002Fchatgpt-nodered-fcn-node","CIlrHztRFem7i2NCSR5MfTu053wqcteciiCLQjLA-Uw",1780070550506]