├── server ├── .gitignore ├── requirements.txt └── app.py ├── example.png ├── client ├── babel.config.js ├── public │ ├── assets │ │ ├── 0.png │ │ ├── 1.png │ │ ├── 2.png │ │ ├── 3.png │ │ ├── 4.png │ │ ├── 5.png │ │ ├── 6.png │ │ ├── 7.png │ │ ├── 8.png │ │ ├── 9.png │ │ └── user.png │ ├── favicon.ico │ ├── index.html │ └── bots.json ├── vue.config.js ├── src │ ├── main.js │ ├── App.vue │ ├── components │ │ ├── Header.vue │ │ ├── SideBar.vue │ │ └── ChatList.vue │ ├── common │ │ └── util.js │ └── store │ │ └── index.js ├── .gitignore ├── jsconfig.json ├── README.md ├── .editorconfig └── package.json ├── .gitignore ├── LICENSE └── README.md /server/.gitignore: -------------------------------------------------------------------------------- 1 | log/ 2 | __pycache__/ 3 | .idea/ -------------------------------------------------------------------------------- /example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChangQingAAS/ChatGPT-Vue-Chat/HEAD/example.png -------------------------------------------------------------------------------- /client/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /client/public/assets/0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChangQingAAS/ChatGPT-Vue-Chat/HEAD/client/public/assets/0.png -------------------------------------------------------------------------------- /client/public/assets/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChangQingAAS/ChatGPT-Vue-Chat/HEAD/client/public/assets/1.png -------------------------------------------------------------------------------- /client/public/assets/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChangQingAAS/ChatGPT-Vue-Chat/HEAD/client/public/assets/2.png -------------------------------------------------------------------------------- /client/public/assets/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChangQingAAS/ChatGPT-Vue-Chat/HEAD/client/public/assets/3.png -------------------------------------------------------------------------------- /client/public/assets/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChangQingAAS/ChatGPT-Vue-Chat/HEAD/client/public/assets/4.png -------------------------------------------------------------------------------- /client/public/assets/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChangQingAAS/ChatGPT-Vue-Chat/HEAD/client/public/assets/5.png -------------------------------------------------------------------------------- /client/public/assets/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChangQingAAS/ChatGPT-Vue-Chat/HEAD/client/public/assets/6.png -------------------------------------------------------------------------------- /client/public/assets/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChangQingAAS/ChatGPT-Vue-Chat/HEAD/client/public/assets/7.png -------------------------------------------------------------------------------- /client/public/assets/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChangQingAAS/ChatGPT-Vue-Chat/HEAD/client/public/assets/8.png -------------------------------------------------------------------------------- /client/public/assets/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChangQingAAS/ChatGPT-Vue-Chat/HEAD/client/public/assets/9.png -------------------------------------------------------------------------------- /client/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChangQingAAS/ChatGPT-Vue-Chat/HEAD/client/public/favicon.ico -------------------------------------------------------------------------------- /client/public/assets/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChangQingAAS/ChatGPT-Vue-Chat/HEAD/client/public/assets/user.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .idea/ 3 | ./client/node_modules/ 4 | ./client/.idea/ 5 | ./server/__pycache__/ 6 | ./server/.idea/ 7 | ./server/log/ -------------------------------------------------------------------------------- /client/vue.config.js: -------------------------------------------------------------------------------- 1 | const { 2 | defineConfig 3 | } = require('@vue/cli-service') 4 | module.exports = defineConfig({ 5 | transpileDependencies: true, 6 | }) 7 | -------------------------------------------------------------------------------- /client/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App' 3 | import Store from '@/store' 4 | // MinUI 5 | import MintUI from 'mint-ui' 6 | import 'mint-ui/lib/style.css' 7 | 8 | Vue.use(MintUI) 9 | 10 | Vue.config.productionTip = false 11 | 12 | new Vue({ 13 | render: h => h(App), 14 | store: Store, 15 | }).$mount('#app') 16 | -------------------------------------------------------------------------------- /client/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | /dist 4 | .idea/ 5 | 6 | 7 | # local env files 8 | .env.local 9 | .env.*.local 10 | 11 | # Log files 12 | npm-debug.log* 13 | yarn-debug.log* 14 | yarn-error.log* 15 | pnpm-debug.log* 16 | 17 | # Editor directories and files 18 | .idea 19 | .vscode 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /client/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "esnext", 5 | "baseUrl": "./", 6 | "moduleResolution": "node", 7 | "paths": { 8 | "@/*": [ 9 | "src/*" 10 | ] 11 | }, 12 | "lib": [ 13 | "esnext", 14 | "dom", 15 | "dom.iterable", 16 | "ScriptHost" 17 | ] 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /client/README.md: -------------------------------------------------------------------------------- 1 | # client 2 | 3 | # Env 4 | - Node: v18.14.2 5 | - Npm: 9.5.0 6 | - Vue2 7 | 8 | ## Project setup 9 | ``` 10 | npm install 11 | ``` 12 | 13 | ### Compiles and hot-reloads for development 14 | ``` 15 | npm run serve 16 | ``` 17 | 18 | ### Compiles and minifies for production 19 | ``` 20 | npm run build 21 | ``` 22 | 23 | ### Lints and fixes files 24 | ``` 25 | npm run lint 26 | ``` 27 | 28 | ### Customize configuration 29 | See [Configuration Reference](https://cli.vuejs.org/config/). 30 | -------------------------------------------------------------------------------- /server/requirements.txt: -------------------------------------------------------------------------------- 1 | aiohttp==3.8.4 2 | aiosignal==1.3.1 3 | async-timeout==4.0.2 4 | attrs==22.2.0 5 | certifi==2022.12.7 6 | charset-normalizer==3.0.1 7 | click==8.1.3 8 | Flask==2.2.3 9 | Flask-Cors==3.0.10 10 | frozenlist==1.3.3 11 | idna==3.4 12 | importlib-metadata==6.0.0 13 | itsdangerous==2.1.2 14 | Jinja2==3.1.2 15 | loguru==0.6.0 16 | MarkupSafe==2.1.2 17 | multidict==6.0.4 18 | openai==0.27.0 19 | requests==2.28.2 20 | six==1.16.0 21 | tqdm==4.65.0 22 | urllib3==1.26.14 23 | Werkzeug==2.2.3 24 | yarl==1.8.2 25 | zipp==3.15.0 26 | -------------------------------------------------------------------------------- /client/src/App.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 21 | 22 | 29 | -------------------------------------------------------------------------------- /client/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | # Replace tabs with spaces; 5 | indent_style = space 6 | # Line indentation 4; 7 | indent_size = 4 8 | # The newline character is `lf`, optional `crlf` or `lf` 9 | end_of_line = lf 10 | # Set the file encoding 11 | charset = utf-8 12 | # Remove trailing blank characters when saving; 13 | trim_trailing_whitespace = true 14 | # Add a newline at the end of the file; 15 | insert_final_newline = true 16 | 17 | 18 | [*.{js,css,html,vue}] 19 | indent_style = space 20 | indent_size = 4 21 | 22 | [*.{md,markdown}] 23 | trim_trailing_whitespace = false 24 | 25 | [Makefile] 26 | indent_style = tab 27 | -------------------------------------------------------------------------------- /client/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | 10 | 11 | 15 |
16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 chang_qing_aas 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /client/src/components/Header.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 25 | 26 | 27 | 53 | -------------------------------------------------------------------------------- /client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "client", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint" 9 | }, 10 | "dependencies": { 11 | "axios": "^1.3.2", 12 | "core-js": "^3.8.3", 13 | "font-awesome": "^4.7.0", 14 | "mint-ui": "^2.2.13", 15 | "vue": "^2.6.14", 16 | "vuex": "^3.6.2" 17 | }, 18 | "devDependencies": { 19 | "@babel/core": "^7.12.16", 20 | "@babel/eslint-parser": "^7.12.16", 21 | "@vue/cli-plugin-babel": "~5.0.0", 22 | "@vue/cli-plugin-eslint": "~5.0.0", 23 | "@vue/cli-service": "~5.0.0", 24 | "eslint-plugin-vue": "^8.0.3", 25 | "vue-template-compiler": "^2.6.14" 26 | }, 27 | "eslintConfig": { 28 | "root": true, 29 | "env": { 30 | "node": true 31 | }, 32 | "extends": [ 33 | "plugin:vue/essential", 34 | "eslint:recommended" 35 | ], 36 | "parserOptions": { 37 | "parser": "@babel/eslint-parser" 38 | }, 39 | "rules": {} 40 | }, 41 | "browserslist": [ 42 | "> 1%", 43 | "last 2 versions", 44 | "not dead" 45 | ] 46 | } 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ChatGPT-VUE-Chat 2 | 3 | ## Description 4 | A simple chat interface with ChatGPT on the left and users on the right. When the 'Send' button is clicked, the prompt is sent to the backend API for processing. 5 | 6 | You can choose who you talk to on the SideBar. 7 | 8 | Here is example: 9 | 10 | ![image](./example.png) 11 | 12 | ### Features 13 | - Before chat formally, `client` load `client/public/bots.json` to initialize the bots, which make the model become different role. 14 | 15 | - The data in json is: 16 | 17 | ```json 18 | ${name of the bot}:${its init prompt} 19 | ``` 20 | 21 | - you can get some init prompt from: 22 | - https://github.com/f/awesome-chatgpt-prompts 23 | - https://github.com/PlexPt/awesome-chatgpt-prompts-zh 24 | 25 | - Need your openai.api_key from "https://platform.openai.com/account/api-keys" 26 | 27 | ## Run 28 | 29 | You'd better run `server` first. 30 | 31 | ### Server 32 | ```shell 33 | cd server 34 | pip3 install -r requirements.txt 35 | python3 app.py 36 | ``` 37 | Because there are not too much packages dependencies, maybe the python version is not a ploblem.(I use python3.11). 38 | 39 | I use openai==0.27.0, because of the new chatgpt api. You'd better make sure the version of openai package. 40 | The package is new, so maybe you could not use 'mirror'. 41 | Just download it like this: 42 | ```sh 43 | pip install -i https://pypi.python.org/simple/ openai==0.27.0 44 | ``` 45 | 46 | ### Client 47 | 48 | #### Reference 49 | 50 | https://github.com/taylorchen709/vue-chat 51 | 52 | ```shell 53 | cd client 54 | nvm install 18 # use node version 18 if possible 55 | npm install 56 | npm run serve 57 | ``` 58 | 59 | ## Noting: 60 | 61 | - At the beginning of this project, I did a combination of BingChatGPT backend and a Vue frontend. 62 | - Later, BingChatGPT did not open the API interface for use. 63 | - Then, I changed the back-end code to an API interface based on OPENAI GPT3 (because ChatGPT is not open anymore), but there is also a problem: too many people use this API, which may cause the connection to fail.(The code maybe redundant.You can modify the redundant code of server/app.py and src/components/ChatList.vue/sendMsg()) 64 | - After openai public chatgpt api at 2023.03.02. **I archive the origin code into branch v1.0.** And write new code in branch main. 65 | - I change name of the repository from `BingChatGPT-Vue-Chat` into `ChatGPT-Vue-Chat`. 66 | - User can talk to different bots at same time 67 | 68 | ## TODO: 69 | 70 | - [x] I want to make more chat interfaces, users can choose who to talk to in the left sidebar, such as a beautiful girl, a handsome man or Elon Musk, etc. 71 | - [ ] The display fails when there are HTML tags in the `content` string of the chat record 72 | - [x] Beautify the sidebar 73 | 74 | 75 | If you have better suggestions, please issue. 76 | -------------------------------------------------------------------------------- /client/src/components/SideBar.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 43 | 44 | 120 | -------------------------------------------------------------------------------- /client/src/common/util.js: -------------------------------------------------------------------------------- 1 | var SIGN_REGEXP = /([yMdhsm])(\1*)/g 2 | var DEFAULT_PATTERN = 'yyyy-MM-dd' 3 | 4 | function padding (s, len) { 5 | len = len - (s + '').length 6 | for (let i = 0; i < len; i++) { 7 | s = '0' + s 8 | } 9 | return s 10 | } 11 | 12 | export default { 13 | getQueryStringByName: function (name) { 14 | var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i') 15 | var r = window.location.search.substr(1).match(reg) 16 | var context = '' 17 | if (r != null) 18 | context = r[2] 19 | reg = null 20 | r = null 21 | return context == null || context == '' || context == 'undefined' ? '' : context 22 | }, 23 | formatDate: { 24 | format: function (date, pattern) { 25 | pattern = pattern || DEFAULT_PATTERN 26 | return pattern.replace(SIGN_REGEXP, function ($0) { 27 | switch ($0.charAt(0)) { 28 | case 'y': 29 | return padding(date.getFullYear(), $0.length) 30 | case 'M': 31 | return padding(date.getMonth() + 1, $0.length) 32 | case 'd': 33 | return padding(date.getDate(), $0.length) 34 | case 'w': 35 | return date.getDay() + 1 36 | case 'h': 37 | return padding(date.getHours(), $0.length) 38 | case 'm': 39 | return padding(date.getMinutes(), $0.length) 40 | case 's': 41 | return padding(date.getSeconds(), $0.length) 42 | } 43 | }) 44 | }, 45 | parse: function (dateString, pattern) { 46 | var matchs1 = pattern.match(SIGN_REGEXP) 47 | var matchs2 = dateString.match(/(\d)+/g) 48 | if (matchs1.length == matchs2.length) { 49 | var _date = new Date(1970, 0, 1) 50 | for (var i = 0; i < matchs1.length; i++) { 51 | var _int = parseInt(matchs2[i]) 52 | var sign = matchs1[i] 53 | switch (sign.charAt(0)) { 54 | case 'y': 55 | _date.setFullYear(_int) 56 | break 57 | case 'M': 58 | _date.setMonth(_int - 1) 59 | break 60 | case 'd': 61 | _date.setDate(_int) 62 | break 63 | case 'h': 64 | _date.setHours(_int) 65 | break 66 | case 'm': 67 | _date.setMinutes(_int) 68 | break 69 | case 's': 70 | _date.setSeconds(_int) 71 | break 72 | } 73 | } 74 | return _date 75 | } 76 | return null 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /client/public/bots.json: -------------------------------------------------------------------------------- 1 | { 2 | "Linux Shell": "I want you to act as a Linux terminal. I'll type the command and you'll reply with what the terminal should display. I want you to only echo terminal output within a unique block of code, and nothing else. Don't write explanations. Do not type commands unless I instruct you to do so. When I need to tell you something in English, I put the text in square brackets [like this]. My first command is pwd", 3 | "English Translator": "I would like you to take on the role of English translation, spell proof and rhetorical improvement. I will communicate with you in any language and you will recognize the language, translate it and answer me in more beautiful and refined English. Please replace my simple words and sentences with more beautiful and elegant expressions, keeping the meaning unchanged but making it more literary. Please only answer corrections and improvements, do not write explanations. My first sentence is \"how are you ?\", please translate it.", 4 | "StoryTeller": "I want you to take on the role of the storyteller. You'll come up with entertaining stories that are compelling, imaginative and captivating for the audience. It can be a fairy tale, an educational story or any other kind of story that has the potential to capture people's attention and imagination. Depending on your target audience, you can choose a specific theme or theme for your storytelling session, for example, if it's children, you can talk about animals; if it's adults, a story based on history might appeal to them better, etc. My first request was \"I need a funny story about perseverance.\"", 5 | "Poet": "I want you to act as a poet. You will create poems that evoke emotions and have the power to stir people’s soul. Write on any topic or theme but make sure your words convey the feeling you are trying to express in beautiful yet meaningful ways. You can also come up with short verses that are still powerful enough to leave an imprint in readers' minds. My first request is \"I need a poem about love.\"", 6 | "AI Writing Tutor": "I want you to act as an AI writing tutor. I will provide you with a student who needs help improving their writing and your task is to use artificial intelligence tools, such as natural language processing, to give the student feedback on how they can improve their composition. You should also use your rhetorical knowledge and experience about effective writing techniques in order to suggest ways that the student can better express their thoughts and ideas in written form. My first request is \"I need somebody to help me edit my master's thesis.\"", 7 | "UX/UI Developer": "I want you to act as a UX/UI developer. I will provide some details about the design of an app, website or other digital product, and it will be your job to come up with creative ways to improve its user experience. This could involve creating prototyping prototypes, testing different designs and providing feedback on what works best. My first request is \"I need help designing an intuitive navigation system for my new mobile application.\"", 8 | "Social Media Manager":"I want you to act as a social media manager. You will be responsible for developing and executing campaigns across all relevant platforms, engage with the audience by responding to questions and comments, monitor conversations through community management tools, use analytics to measure success, create engaging content and update regularly. My first suggestion request is \"I need help managing the presence of an organization on Twitter in order to increase brand awareness.\"", 9 | "Scientific Data Visualizer":"I want you to act as a scientific data visualizer. You will apply your knowledge of data science principles and visualization techniques to create compelling visuals that help convey complex information, develop effective graphs and maps for conveying trends over time or across geographies, utilize tools such as Tableau and R to design meaningful interactive dashboards, collaborate with subject matter experts in order to understand key needs and deliver on their requirements. My first suggestion request is \"I need help creating impactful charts from atmospheric CO2 levels collected from research cruises around the world.\"" 10 | } 11 | -------------------------------------------------------------------------------- /server/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, request 2 | from flask_cors import CORS 3 | from loguru import logger 4 | import openai 5 | 6 | # flask configuration-------------------------------------------------------------- 7 | DEBUG = True 8 | 9 | # instantiate the app 10 | app = Flask(__name__) 11 | # Load configuration variables 12 | app.config.from_object(__name__) 13 | 14 | # enable CORS 15 | CORS(app, resources={r'/*': {'origins': '*'}}) 16 | # flask configuration-------------------------------------------------------------- 17 | 18 | 19 | # openai chatGPT configuration-------------------------------------------------------------- 20 | openai.api_key = "https://platform.openai.com/playground" 21 | # init_prompt = "" # it can make chatGPT be some different role, for example: beautiful girl. 22 | 23 | # By global `all_messages`, we can use it easily. 24 | # it includes every bot&user messages. 25 | all_messages = {} 26 | 27 | 28 | # openai chatGPT configuration-------------------------------------------------------------- 29 | 30 | 31 | # def chat_init(): 32 | # """ 33 | # 1.input init prompt to model 34 | # 2.add the two message into the complete messages for chatting 35 | # 36 | # during this, log something for DEBUG in the future 37 | # """ 38 | # completion = openai.ChatCompletion.create( 39 | # # model name 40 | # # choose other model from: https://platform.openai.com/docs/models/overview 41 | # model="gpt-3.5-turbo", # or "gpt-3.5-turbo-0301" 42 | # # chat history, make the model aware of the current context 43 | # messages=[{ 44 | # "role": "user", 45 | # "content": init_prompt 46 | # }], 47 | # # The parameters below maybe could not be used 48 | # # Control the randomness of the result, 0.0 means the result is fixed, and the randomness can be set to 0.9. 49 | # # temperate=0.5, 50 | # 51 | # # The maximum number of words returned (including questions and answers), usually Chinese characters occupy 52 | # # two tokens. Assuming it is set to 100, if there are 40 Chinese characters in the prompt question, 53 | # # then the returned result will include at most 10 Chinese characters. The maximum number of tokens allowed 54 | # # by the ChatGPT API is 4096, that is, the max_tokens maximum setting is 4096 minus the number of tokens in 55 | # # question. 56 | # # max_tokens=1000, 57 | # 58 | # # top_p=1, 59 | # # frequency_penalty=0, 60 | # # presence_penalty=0 61 | # ) 62 | # logger.info("user: " + init_prompt) 63 | # 64 | # message = completion["choices"][0]["message"] 65 | # messages.append(message) 66 | # logger.info("chatGPT: " + message['content']) 67 | 68 | 69 | def get_answer_from_bot(bot_name, prompt): 70 | """ 71 | 1.prepare the input message according the bot which you talk to 72 | 2.input the complete messages into model, to get the answer 73 | 74 | during this, log something for DEBUG in the future 75 | """ 76 | try: 77 | messages = all_messages[bot_name] 78 | except KeyError: 79 | logger.info("all_messages[%s] is none, so init it." % bot_name) 80 | all_messages[bot_name] = [] 81 | messages = all_messages[bot_name] 82 | 83 | messages.append({ 84 | "role": "user", 85 | "content": prompt 86 | }) 87 | logger.info("user: " + prompt) 88 | 89 | completion = openai.ChatCompletion.create( 90 | model="gpt-3.5-turbo", 91 | messages=messages, 92 | ) 93 | 94 | message = completion["choices"][0]["message"] 95 | messages.append(message) 96 | logger.info("%s: %s" % (bot_name, message['content'])) 97 | 98 | return message['content'] 99 | 100 | 101 | @app.route('/get_answer', methods=['GET', 'POST']) 102 | def get_answer(): 103 | post_data = request.get_json() 104 | logger.info("post_data: " + str(post_data)) 105 | prompt = post_data["prompt"] 106 | bot_name = post_data["bot"] 107 | 108 | return { 109 | 'status': 'success', 110 | "answer": get_answer_from_bot(bot_name, prompt) 111 | } 112 | 113 | 114 | if __name__ == '__main__': 115 | logger.add( 116 | "./log/run.log", 117 | encoding="utf-8", 118 | format="{level} | {time:YYYY-MM-DD HH:mm:ss} | {file} | {line} | {message}", 119 | retention="30 days", 120 | rotation="500 MB" 121 | ) 122 | logger.info("System initializing.") 123 | 124 | # # Before officially using the model, initialize the model by giving it `init_prompt` 125 | # chat_init() 126 | 127 | # Bind to all network interfaces 128 | app.run(host='0.0.0.0', port=5000) 129 | -------------------------------------------------------------------------------- /client/src/store/index.js: -------------------------------------------------------------------------------- 1 | // Import and use Vuex 2 | import Vuex from 'vuex' 3 | import Vue from 'vue' 4 | import util from '@/common/util' 5 | import axios from 'axios' 6 | 7 | Vue.use(Vuex) 8 | 9 | // actions in the corresponding component 10 | const actions = { 11 | // before the chat, use `bots.json` to load bot_name and init_prompt 12 | async fetchBots (context) { 13 | try { 14 | const response = await fetch('bots.json') 15 | const data = await response.json() 16 | context.commit('INIT_BOTS', data) 17 | } catch (error) { 18 | console.error(error) 19 | } 20 | } 21 | } 22 | 23 | // manipulating data in `state` 24 | const mutations = { 25 | SEND_MESSAGE (state, payload) { 26 | // console.log('SEND_MESSAGE in mutations is called.') 27 | // bot to user 28 | if (payload.receiver === 'user') { 29 | for (let bot of state.bots) { 30 | if (bot.name === payload.sender) { 31 | bot.messages.push({ 32 | content: payload.content, 33 | sender: payload.sender, 34 | receiver: payload.receiver, 35 | time: payload.time, 36 | }) 37 | } 38 | } 39 | return 40 | } 41 | 42 | // user to bot 43 | for (let bot of state.bots) { 44 | if (bot.name === payload.receiver) { 45 | bot.messages.push({ 46 | content: payload.content, 47 | sender: payload.sender, 48 | receiver: payload.receiver, 49 | time: payload.time, 50 | }) 51 | } 52 | } 53 | 54 | }, 55 | 56 | SET_CURRENT_BOT (state, value) { 57 | // console.log('SET_CURRENT_BOT in mutation is called.') 58 | state.currentBotIndex = value 59 | }, 60 | 61 | // before the chat, use `bots.json` to load bot_name and init_prompt 62 | INIT_BOTS: function (state, value) { 63 | for (let bot_name in value) { 64 | let init_prompt = value[bot_name] 65 | state.bots.push({ 66 | name: bot_name, 67 | avatar: 'assets/' + Math.floor(Math.random() * 10) + '.png', 68 | init_prompt: init_prompt, 69 | messages: [] 70 | }) 71 | } 72 | // console.log("init bots are: ",state.bots) 73 | 74 | /* 75 | Somehow, if I write the code of sending `init_prompt` in `created()` of other components 76 | after initializing the data structure of bots, 77 | Code does not perform as expected, so I wrote the code here. 78 | I speculate that it is due to the asynchronous execution mechanism of js and some mechanisms of vuex. 79 | Fortunately, it is not a big problem to write the code here. 80 | If you have better suggestions, please contact me. 81 | */ 82 | // before chat to the bot, send the init_prompt to the bot 83 | for (let bot of state.bots) { 84 | console.log('send init prompt to ', bot.name) 85 | 86 | // user send init prompts of all bots 87 | this.commit('SEND_MESSAGE', { 88 | content: bot.init_prompt, 89 | sender: 'user', 90 | receiver: bot.name, 91 | time: util.formatDate.format(new Date(), 'yyyy-MM-dd hh:mm:ss') 92 | }) 93 | 94 | // make a request to server 95 | const param = { 96 | 'bot': bot.name, 97 | 'prompt': bot.init_prompt, 98 | } 99 | const path = `http://${window.location.hostname}:5000/get_answer` 100 | axios.post(path, param) 101 | .then((res) => { 102 | this.commit('SEND_MESSAGE', { 103 | content: res.data['answer'], 104 | sender: bot.name, 105 | receiver: 'user', 106 | time: util.formatDate.format(new Date(), 'yyyy-MM-dd hh:mm:ss') 107 | }) 108 | }) 109 | .catch((error) => { 110 | this.commit('SEND_MESSAGE', { 111 | content: `${bot.name} happened error: ${error}`, 112 | sender: bot.name, 113 | receiver: 'user', 114 | time: util.formatDate.format(new Date(), 'yyyy-MM-dd hh:mm:ss') 115 | }) 116 | }) 117 | } 118 | } 119 | } 120 | 121 | // Storing data 122 | const state = { 123 | currentBotIndex: 0, 124 | bots: [], 125 | } 126 | 127 | // Create and export Store 128 | export default new Vuex.Store({ 129 | actions: actions, 130 | mutations: mutations, 131 | state: state 132 | }) 133 | -------------------------------------------------------------------------------- /client/src/components/ChatList.vue: -------------------------------------------------------------------------------- 1 | 30 | 31 | 126 | 127 | 319 | --------------------------------------------------------------------------------