├── ChatGPT.png ├── ChatGPTforNuke.py ├── nuke.png └── runthecode.png /ChatGPT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiachengXuGit/ChatGPTforNuke/939c13ba776d955ad6d17c61c58fe1b17b8badf8/ChatGPT.png -------------------------------------------------------------------------------- /ChatGPTforNuke.py: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------- 2 | # ChatGTPforNuke v1.1 by Jiacheng Xu 3 | # A chatbot using openai module 4 | # 2023 5 | # ------------------------------------------------------------------------------- 6 | 7 | 8 | from PySide2 import QtWidgets, QtCore, QtGui 9 | import openai 10 | import getpass, re, traceback, nuke 11 | 12 | 13 | icon_path = "C:/Users/" + getpass.getuser() + "/.nuke/" 14 | 15 | class ChatGPT(QtWidgets.QWidget): 16 | def __init__(self): 17 | super(ChatGPT, self).__init__() 18 | # Set up the OpenAI API client 19 | self.code_blocks = '' 20 | openai.api_key = 'OPENAI_API_KEY' 21 | self.conversation = [{"role": "system", 22 | "content": "helpful assistant. Will help Nuke(Foundry) related question, python, tcl, Nuke expression, BlinkScript."}] 23 | 24 | # Set window properties 25 | self.setWindowTitle('ChatGPT') 26 | self.setWindowFlag(QtCore.Qt.WindowStaysOnTopHint) 27 | self.setMinimumSize(420, 600) 28 | self.setWindowIcon(QtGui.QIcon(icon_path + 'ChatGPT.png')) 29 | 30 | # Set background color and font 31 | self.setStyleSheet("background-color: #323232; sans-serif; font-size: 14px;") 32 | 33 | # Create message input 34 | self.message_input = QtWidgets.QTextEdit() 35 | self.message_input.setAcceptRichText(False) 36 | self.message_input.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) 37 | self.message_input.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) 38 | self.message_input.setStyleSheet("background-color: #3a3a3a; color: #ffffff; border: 1px solid #1f1f1f; \ 39 | border-radius: 5px; padding: 10px;") 40 | 41 | # Create response output 42 | self.response_output = QtWidgets.QTextEdit() 43 | self.response_output.setReadOnly(True) 44 | self.response_output.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) 45 | self.response_output.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) 46 | self.response_output.setStyleSheet("background-color: #3a3a3a; color: #ffffff; border: 1px solid #1f1f1f; \ 47 | border-radius: 5px; padding: 10px;") 48 | 49 | # Create send button 50 | send_button = QtWidgets.QPushButton('Send') 51 | send_button.setFixedHeight(25) 52 | gradient = "qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #464646, stop:1 #545454);" 53 | send_button.setStyleSheet(f"background: {gradient}; color: #c8c8c8; border: 1px solid #1f1f1f; \ 54 | border-radius: 5px; padding: 1px;") 55 | send_button.clicked.connect(self.send_message) 56 | 57 | # Create clear button 58 | clear_button = QtWidgets.QPushButton('Clear') 59 | clear_button.setFixedHeight(25) 60 | clear_button.setStyleSheet(f"background: {gradient}; color: #c8c8c8; border: 1px solid #1f1f1f; \ 61 | border-radius: 5px; padding: 1px; ") 62 | clear_button.clicked.connect(self.clear_messages) 63 | 64 | # Create run button 65 | run_button = QtWidgets.QPushButton('Run Script') 66 | 67 | run_button.setFixedHeight(25) 68 | run_button.setStyleSheet(f"background: {gradient}; color: #c8c8c8; border: 1px solid #1f1f1f; \ 69 | border-radius: 5px; padding: 1px; ") 70 | 71 | icon = QtGui.QIcon(icon_path + 'runthecode.png') 72 | run_button.setIcon(icon) 73 | run_button.setIconSize(icon.actualSize(QtCore.QSize(15, 15))) 74 | run_button.setLayoutDirection(QtCore.Qt.RightToLeft) 75 | 76 | run_button.clicked.connect(self.run_script) 77 | 78 | # Create layout 79 | layout = QtWidgets.QVBoxLayout() 80 | layout.addWidget(self.response_output, 80) 81 | layout.addWidget(self.message_input, 20) 82 | button_layout = QtWidgets.QHBoxLayout() 83 | button_layout.addWidget(send_button) 84 | button_layout.addWidget(run_button) 85 | button_layout.addWidget(clear_button) 86 | layout.addLayout(button_layout) 87 | 88 | # Set layout 89 | self.setLayout(layout) 90 | 91 | # Send a message to ChatGPT and update the UI with the response 92 | def send_message(self): 93 | message = self.message_input.toPlainText() 94 | 95 | prompt = "" 96 | 97 | prompt += "You: " + message + "\nChatGPT:" 98 | response = self.get_chat_response(message) 99 | 100 | # Add icons before "you" and "chatgpt" 101 | cursor = self.response_output.textCursor() 102 | cursor.movePosition(QtGui.QTextCursor.End) 103 | cursor.insertText('\n') 104 | image_format = QtGui.QTextImageFormat() 105 | image_format.setName(icon_path + 'nuke.png') 106 | image_format.setWidth(16) 107 | image_format.setHeight(16) 108 | cursor.insertImage(image_format) 109 | 110 | cursor.insertText(' ') 111 | cursor.insertHtml('You: ') 112 | cursor.insertText('\n') 113 | cursor.insertText(message) 114 | cursor.insertText('\n\n') 115 | image_format2 = QtGui.QTextImageFormat() 116 | image_format2.setName(icon_path + 'ChatGPT.png') 117 | image_format2.setWidth(16) 118 | image_format2.setHeight(16) 119 | cursor.insertImage(image_format2) 120 | 121 | cursor.insertText(' ') 122 | cursor.insertHtml('ChatGPT: ') 123 | cursor.insertText('\n') 124 | cursor.insertText(response) 125 | cursor.insertText('\n\n') 126 | self.response_output.ensureCursorVisible() 127 | 128 | self.message_input.clear() 129 | 130 | # Clear previous messages and responses 131 | def clear_messages(self): 132 | self.conversation = [{"role": "system", 133 | "content": "helpful assistant. Will help Nuke(Foundry) related question, python, tcl, Nuke expression, BlinkScript."}] 134 | self.response_output.clear() 135 | self.code_blocks = '' 136 | 137 | # Send a message to ChatGPT and return the response 138 | 139 | def get_chat_response(self, message): 140 | 141 | self.conversation.append({"role": "user", "content": message}) 142 | 143 | # Define custom prompts and responses as a dictionary 144 | custom_prompts = { 145 | "latest sequence cut": "Here are the latest sequence cut:\n/jobs/show/shots/se_seq/se_seq_cut.mov \n/jobs/show/shots/tb_seq/tb_seq_cut.mov\n/jobs/show/shots/op_seq/op_seq_cut.mov", 146 | "reference shots": "Here are the reference shows for each sequence:\n se_seq: se0010 se0145 se0212\n tb_seq: tb0240 tb0500 tb010 \n \nContact to your lead if you any" 147 | " further questions: \n Jackie Chan jac@domain.com \n Jet Li jel@domain.com ", 148 | "element library": "Here is the element library: \n https://jiachengx.com/", 149 | # Add more custom prompts and responses here 150 | } 151 | # Handle custom prompts 152 | if message.lower() in custom_prompts: 153 | return custom_prompts[message] 154 | else: 155 | # Use OpenAI API to get response for other prompts 156 | try: 157 | response = openai.ChatCompletion.create( 158 | model="gpt-3.5-turbo", 159 | messages=self.conversation, 160 | temperature=0, 161 | max_tokens=2048, 162 | top_p=1 163 | ) 164 | self.conversation.append({"role": "assistant", "content": response['choices'][0]['message']['content']}) 165 | 166 | response_text = response['choices'][0]['message']['content'] 167 | 168 | # Define a regular expression pattern to match the code blocks 169 | pattern = r"```(?:\w+\n)?([\s\S]+?)```" 170 | 171 | 172 | # Find all occurrences of the pattern in the text 173 | matches = re.findall(pattern, response_text) 174 | if matches: 175 | # Join all the extracted code blocks into a single string 176 | self.code_blocks = "\n".join(matches) 177 | #print(self.code_blocks) 178 | 179 | else: 180 | print("No code blocks found.") 181 | 182 | return response_text 183 | 184 | except Exception as e: 185 | # display error message box pop-up 186 | app = QtWidgets.QApplication.instance() 187 | if app is None: 188 | app = QtWidgets.QApplication([]) 189 | msg_box = QtWidgets.QMessageBox() 190 | msg_box.setIcon(QtWidgets.QMessageBox.Critical) 191 | msg_box.setText(f"An error occurred: {str(e)}") 192 | msg_box.setWindowTitle("Error") 193 | msg_box.exec_() 194 | return "Please click the clear button" 195 | 196 | def run_script(self): 197 | 198 | 199 | try: 200 | 201 | script = self.code_blocks 202 | print(script) 203 | exec(script) 204 | 205 | 206 | 207 | except Exception as e: 208 | # capture the error message as a string 209 | error_str = ''.join(traceback.format_exception(type(e), e, e.__traceback__)) 210 | 211 | # remove the second line from the error message 212 | error_str = error_str.split('\n', 2)[0] + '\n' + error_str.split('\n', 2)[2] 213 | 214 | # print the modified error message 215 | print(error_str) 216 | 217 | 218 | 219 | -------------------------------------------------------------------------------- /nuke.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiachengXuGit/ChatGPTforNuke/939c13ba776d955ad6d17c61c58fe1b17b8badf8/nuke.png -------------------------------------------------------------------------------- /runthecode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiachengXuGit/ChatGPTforNuke/939c13ba776d955ad6d17c61c58fe1b17b8badf8/runthecode.png --------------------------------------------------------------------------------