├── LICENSE ├── README.md ├── client ├── package.json ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt └── src │ ├── App.js │ ├── App.test.js │ ├── assets │ ├── camelagi.png │ ├── discord.svg │ ├── google.svg │ ├── key.svg │ ├── logout-white.svg │ ├── question-mark.svg │ ├── reload.svg │ ├── send.svg │ ├── share-white.svg │ ├── user-1.svg │ ├── user-2.svg │ ├── user-3.svg │ ├── user-4.svg │ └── user.png │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── pages │ ├── AgentConvo.js │ └── AgentConvoShare.js │ ├── reportWebVitals.js │ ├── setupTests.js │ └── styles │ ├── agent-convo.css │ └── home.css ├── server ├── agent_convo.py ├── database.py ├── requirements.txt └── webserver.py └── steps_to_run.md /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 SamurAIGPT 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Camel-AutoGPT 2 | 3 | You must have seen how powerful AI agents are with AutoGPT/BabyAGI ⚡️ 4 | 5 | Imagine 2 of these agents interacting on a common goal🤯 6 | 7 | Camel AutoGPT allows you to configure and deploy communicating Autonomous AI agents. Name your own custom AI characters and have them embark on any goal imaginable 🚀. 8 | 9 | ### 🎉 Roadmap 10 | 11 | * Share agents conversation 🔗 12 | 13 | * Saving agent runs 💾 14 | 15 | * Prefixed instructor/assistant examples 🧠 16 | 17 | * Web browsing capabilities 🌐 18 | 19 | * Writing capabilities via a document API 📄 20 | 21 | * More Coming soon... 22 | 23 | ### Getting Started 24 | 25 | Code is up, ⭐ (Star) the repo to receive updates 26 | 27 | Follow [Anil Chandra Naidu Matcha](https://twitter.com/matchaman11) & [Ankur Singh](https://twitter.com/ankur_maker) on twitter for updates 28 | 29 | ### How to run ? 30 | 31 | Follow steps from here https://github.com/SamurAIGPT/Camel-AutoGPT/blob/main/steps_to_run.md 32 | 33 | ### References 34 | 35 | https://github.com/lightaime/camel 36 | 37 | ### Demo link 38 | 39 | https://camelagi.thesamur.ai/ 40 | 41 | ### Support 42 | 43 | Join our discord https://discord.gg/A6EzvsKX4u to get support 44 | -------------------------------------------------------------------------------- /client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "autogpt", 3 | "version": "0.1.0", 4 | "private": true, 5 | "proxy": "http://localhost:5000", 6 | "dependencies": { 7 | "@reduxjs/toolkit": "^1.9.0", 8 | "@testing-library/jest-dom": "^5.16.5", 9 | "@testing-library/react": "^13.4.0", 10 | "@testing-library/user-event": "^13.5.0", 11 | "axios": "^1.2.0", 12 | "bootstrap": "^5.2.3", 13 | "react": "^18.2.0", 14 | "react-bootstrap": "^2.6.0", 15 | "react-dom": "^18.2.0", 16 | "react-markdown": "^8.0.5", 17 | "react-redux": "^8.0.5", 18 | "react-router-dom": "^6.4.3", 19 | "react-scripts": "5.0.1", 20 | "react-toastify": "^9.1.1", 21 | "remark-gfm": "^3.0.1", 22 | "web-vitals": "^2.1.4" 23 | }, 24 | "scripts": { 25 | "start": "react-scripts start", 26 | "build": "react-scripts build", 27 | "test": "react-scripts test", 28 | "eject": "react-scripts eject" 29 | }, 30 | "eslintConfig": { 31 | "extends": [ 32 | "react-app", 33 | "react-app/jest" 34 | ] 35 | }, 36 | "browserslist": { 37 | "production": [ 38 | ">0.2%", 39 | "not dead", 40 | "not op_mini all" 41 | ], 42 | "development": [ 43 | "last 1 chrome version", 44 | "last 1 firefox version", 45 | "last 1 safari version" 46 | ] 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /client/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SamurAIGPT/GPT-Agent/bbcd4adf887897396a7c021784e7a67dc557a567/client/public/favicon.ico -------------------------------------------------------------------------------- /client/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 19 | 20 | 21 | 22 | 31 | AutoGPT 32 | 33 | 34 | 35 |
36 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /client/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SamurAIGPT/GPT-Agent/bbcd4adf887897396a7c021784e7a67dc557a567/client/public/logo192.png -------------------------------------------------------------------------------- /client/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SamurAIGPT/GPT-Agent/bbcd4adf887897396a7c021784e7a67dc557a567/client/public/logo512.png -------------------------------------------------------------------------------- /client/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /client/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /client/src/App.js: -------------------------------------------------------------------------------- 1 | import './styles/home.css'; 2 | import { BrowserRouter, Route, Routes,Navigate } from 'react-router-dom'; 3 | import AgentConvo from './pages/AgentConvo'; 4 | import AgentConvoShare from './pages/AgentConvoShare'; 5 | 6 | 7 | function App() { 8 | return ( 9 |
10 | 11 | 12 | }/> 13 | }/> 14 | 15 | 16 |
17 | ); 18 | } 19 | 20 | export default App; 21 | -------------------------------------------------------------------------------- /client/src/App.test.js: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | import App from './App'; 3 | 4 | test('renders learn react link', () => { 5 | render(); 6 | const linkElement = screen.getByText(/learn react/i); 7 | expect(linkElement).toBeInTheDocument(); 8 | }); 9 | -------------------------------------------------------------------------------- /client/src/assets/camelagi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SamurAIGPT/GPT-Agent/bbcd4adf887897396a7c021784e7a67dc557a567/client/src/assets/camelagi.png -------------------------------------------------------------------------------- /client/src/assets/discord.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/src/assets/google.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | ionicons-v5_logos 8 | 9 | 10 | -------------------------------------------------------------------------------- /client/src/assets/key.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /client/src/assets/logout-white.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/src/assets/question-mark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 13 | 14 | -------------------------------------------------------------------------------- /client/src/assets/reload.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 11 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /client/src/assets/send.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/src/assets/share-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /client/src/assets/user-1.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/src/assets/user-2.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/src/assets/user-3.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/src/assets/user-4.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/src/assets/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SamurAIGPT/GPT-Agent/bbcd4adf887897396a7c021784e7a67dc557a567/client/src/assets/user.png -------------------------------------------------------------------------------- /client/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /client/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | import "bootstrap/dist/css/bootstrap.min.css"; 7 | 8 | const root = ReactDOM.createRoot(document.getElementById('root')); 9 | root.render( 10 | 11 | 12 | 13 | ); 14 | 15 | // If you want to start measuring performance in your app, pass a function 16 | // to log results (for example: reportWebVitals(console.log)) 17 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 18 | reportWebVitals(); 19 | -------------------------------------------------------------------------------- /client/src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/src/pages/AgentConvo.js: -------------------------------------------------------------------------------- 1 | import {useState,useEffect,useRef} from 'react'; 2 | import '../styles/agent-convo.css' 3 | import { Button, Stack, Image, Form, Row, Col, Spinner, InputGroup,FormControl, Modal } from "react-bootstrap"; 4 | import { ReactComponent as ReloadIcon } from "../assets/reload.svg"; 5 | import { ReactComponent as KeyIcon } from "../assets/key.svg"; 6 | import { ReactComponent as LogoutIcon } from "../assets/logout-white.svg"; 7 | import { ReactComponent as Bot1Icon } from "../assets/user-1.svg"; 8 | import { ReactComponent as Bot2Icon } from "../assets/user-2.svg"; 9 | import { ReactComponent as Bot3Icon } from "../assets/user-3.svg"; 10 | import { ReactComponent as Bot4Icon } from "../assets/user-4.svg"; 11 | import logoImage from '../assets/camelagi.png' 12 | import {ReactComponent as SendIcon} from '../assets/send.svg' 13 | import { ToastContainer, toast } from 'react-toastify'; 14 | import {ReactComponent as GoogleIcon} from '../assets/google.svg' 15 | import { ReactComponent as DiscordIcon } from "../assets/discord.svg"; 16 | import axios from "axios" 17 | import ReactMarkdown from 'react-markdown' 18 | import remarkGfm from 'remark-gfm' 19 | import { ReactComponent as ShareIcon } from "../assets/share-white.svg"; 20 | 21 | 22 | function AgentConvo() { 23 | const [isLoggedIn,setIsLoggedIn] = useState(false); 24 | const [authUrl,setAuthUrl] = useState("") 25 | const [ranUser1, setRanUser1] = useState(null); 26 | const [ranUser2, setRanUser2] = useState(null); 27 | const [started, setStarted] = useState(false); 28 | const [key, setKey] = useState(""); 29 | const [task, setTask] = useState(""); 30 | const [finished, setFinished] = useState(false); 31 | const [keyAdded, setKeyAdded] = useState(false); 32 | const [user, setUser] = useState(false); 33 | const [role1, setRole1] = useState(""); 34 | const [role2, setRole2] = useState(""); 35 | const [chat,setChat] = useState([]) 36 | const [sessId,setSessId] = useState(0) 37 | const [showBanner, setShowBanner] = useState(false); 38 | const [turn,setTurn] = useState(0) 39 | const sessionRef = useRef(null) 40 | sessionRef.current = sessId 41 | const chatRef = useRef(null) 42 | chatRef.current = chat 43 | const turnRef = useRef(null) 44 | turnRef.current = turn 45 | 46 | let fetchMessages = () => { 47 | setChat([...chatRef.current,{role:0,msg:null}]) 48 | 49 | axios.post("/rp/start",{role1:role1,role2:role2,task:task,sessId:sessionRef.current}).then((res)=>{ 50 | setSessId(res.data.sessId) 51 | if(res.data.convoEnd==true){ 52 | setFinished((prev)=>true) 53 | }else{ 54 | chatRef.current.at(-1).msg = res.data.userMsg 55 | setChat([...chatRef.current,{role:1,msg:null}]) 56 | setTimeout(() => { 57 | chatRef.current.at(-1).msg = res.data.assistantMsg; 58 | setTurn((prev)=>prev+1) 59 | startDiscussion(false) 60 | }, 3000); 61 | // setUpdate((prev)=>!prev) 62 | 63 | } 64 | 65 | }) 66 | .catch((err)=>{ 67 | toast("Failed to respond " + err.response.data); 68 | }) 69 | } 70 | 71 | let startDiscussion = (newTurn) => { 72 | let getTurn = turnRef.current 73 | if(newTurn==true){ 74 | getTurn = 0 75 | setTurn((prev)=>0) 76 | setStarted((prev)=>true) 77 | } 78 | 79 | if(getTurn<2){ 80 | fetchMessages() 81 | } 82 | } 83 | 84 | const addKey = () => { 85 | axios.post("/store_key",{key:key}).then((res)=>{ 86 | setKeyAdded(true) 87 | }).catch((err)=>{ 88 | toast("Key cannot be verified, try again"); 89 | }) 90 | } 91 | 92 | const logout = () => { 93 | axios.get("/heybot/logout").then((res)=>{ 94 | window.location.reload(); 95 | }).catch((err)=>{ 96 | console.log(err) 97 | }) 98 | } 99 | 100 | const shareChat = () => { 101 | navigator.clipboard.writeText(window.location.host+'/conversation/share?session='+sessionRef.current) 102 | window.open('/conversation/share?session='+sessionRef.current, "_blank"); 103 | } 104 | 105 | useEffect(() => { 106 | setRanUser1(Math.random()) 107 | setRanUser2(Math.random()) 108 | axios.get("/rp/isLoggedIn").then((res)=>{ 109 | setIsLoggedIn(res.data.isLoggedIn) 110 | if(res.data.isLoggedIn == false){ 111 | setAuthUrl(res.data.auth_url) 112 | }else{ 113 | setUser({id:res.data.userId,image:res.data.image}) 114 | if(res.data.key_added==null){ 115 | setKeyAdded((prev)=>false) 116 | }else{ 117 | setKeyAdded((prev)=>true) 118 | setKey(res.data.key_added) 119 | } 120 | 121 | } 122 | }).catch((err)=>{ 123 | console.log(err) 124 | }) 125 | 126 | window.setTimeout(()=>setShowBanner(true),30000) 127 | },[]) 128 | useEffect(() => { 129 | if(document.querySelector('.end-chat')!=null){document.querySelector('.end-chat').scrollIntoView({ behavior: 'smooth', block: 'end' });} 130 | }, [chat]) 131 | 132 | return ( 133 | <> 134 |
135 |
136 |
137 |

CamelAGI

138 | {isLoggedIn&&
139 | window.location.reload()} className="icon"/> 140 | {setKeyAdded(false)} className="icon"/>} 141 | 142 |
} 143 |
144 | {isLoggedIn? 145 | 146 | {keyAdded? 147 | <> 148 | {started? 149 | <> 150 | 151 | {chatRef.current.length>0&&chatRef.current.map((message)=> 152 | message.role==0? 153 |
154 | {ranUser1!=null&&ranUser1>0.5?:} 155 |
156 |
157 | {message.msg==null? 158 | 159 | 160 | 161 | 162 | : 163 |

} 164 |
165 | {role1} 166 |
167 |
: 168 |
169 |
170 |
171 | {message.msg==null? 172 | 173 | 174 | 175 | 176 | : 177 |

} 178 |
179 | {role2} 180 |
181 | {ranUser2!=null&&ranUser2>0.5?:} 182 |
183 | )} 184 | {sessionRef.current!=0&&} 185 |
186 |
187 | {finished? 188 |
Task Completed!
189 | : 190 | <> 191 | {turnRef.current<3? 192 | 193 | :} 194 | } 195 | 196 | : 197 | <> 198 |
Get started with a task to discuss
199 | 200 | Enter Role of the Instructor 201 | setRole1(e.target.value)}/> 202 | 203 | 204 | Enter Role of the Assistant 205 | setRole2(e.target.value)}/> 206 | 207 | 208 | Enter topic of discussion 209 | setTask(e.target.value)}/> 210 | 211 | 212 | 213 | 214 | } 215 | : 216 | 217 |
Add your OpenAI Key
218 |

Get your OpenAI Key by signing up/ logging in from the OpenAI Dashboard. Go to Dashboard

219 | 220 | setKey(e.target.value)} 224 | onKeyDown={(e)=>{e.code=="Enter"&&addKey()}} 225 | /> 226 | 229 | 230 | Watch this video to get started 231 | 232 |
233 | } 234 |
: 235 | 236 | 237 | {/*
Login to agi
*/} 238 |
Accomplish your task with AI agents
239 | 240 | 241 | {/* navigate('/agi/faq')}> Know More */} 242 |
243 | } 244 |
245 | 246 | setShowBanner(false)}> 247 | 248 | setShowBanner(false)} className="position-absolute top-0 end-0 me-4 mt-2">X 249 | 250 | Camel AGI - Communicative Agents on GPT | Product Hunt 251 | Join Our Discord 252 | Star CamelAGI on Github 253 | 254 | 255 | 256 |
257 | 258 | ) 259 | 260 | } 261 | 262 | export default AgentConvo; -------------------------------------------------------------------------------- /client/src/pages/AgentConvoShare.js: -------------------------------------------------------------------------------- 1 | import {useState,useEffect,useRef} from 'react'; 2 | import '../styles/agent-convo.css' 3 | import { Button, Stack, Image, Form,Modal, Spinner, } from "react-bootstrap"; 4 | import { ReactComponent as Bot1Icon } from "../assets/user-1.svg"; 5 | import { ReactComponent as Bot2Icon } from "../assets/user-2.svg"; 6 | import { ReactComponent as Bot3Icon } from "../assets/user-3.svg"; 7 | import { ReactComponent as Bot4Icon } from "../assets/user-4.svg"; 8 | import logoImage from '../assets/camelagi.png' 9 | import { useNavigate } from "react-router-dom"; 10 | import { ToastContainer, toast } from 'react-toastify'; 11 | import axios from "axios" 12 | import ReactMarkdown from 'react-markdown' 13 | import remarkGfm from 'remark-gfm' 14 | import { ReactComponent as ShareIcon } from "../assets/share-white.svg"; 15 | import { useSearchParams, useParams } from "react-router-dom"; 16 | 17 | 18 | function AgentConvoShare() { 19 | 20 | const [ranUser1, setRanUser1] = useState(null); 21 | const [ranUser2, setRanUser2] = useState(null); 22 | const navigate = useNavigate() 23 | const [showBanner, setShowBanner] = useState(false); 24 | const [user, setUser] = useState(false); 25 | const [role1, setRole1] = useState(""); 26 | const [role2, setRole2] = useState(""); 27 | const [task, setTask] = useState(""); 28 | const [chat,setChat] = useState([]) 29 | const [sessId,setSessId] = useState(0) 30 | const sessionRef = useRef(null) 31 | sessionRef.current = sessId 32 | const chatRef = useRef(null) 33 | chatRef.current = chat 34 | let [searchParams, setSearchParams] = useSearchParams(); 35 | 36 | 37 | useEffect(() => { 38 | setRanUser1(Math.random()) 39 | setRanUser2(Math.random()) 40 | axios.get("/rp/get_chat?sessId="+searchParams.get("session")).then((res)=>{ 41 | setChat(res.data.messages) 42 | setRole1(res.data.role1) 43 | setRole2(res.data.role2) 44 | setTask(res.data.task) 45 | 46 | 47 | }).catch((err)=>{ 48 | console.log(err) 49 | }) 50 | window.setTimeout(()=>setShowBanner(true),30000) 51 | },[]) 52 | // useEffect(() => { 53 | // if(document.querySelector('.end-chat')!=null){document.querySelector('.end-chat').scrollIntoView({ behavior: 'smooth', block: 'end' });} 54 | // }, [chat]) 55 | 56 | return ( 57 | <> 58 |
59 |
60 |
61 |

CamelAGI

62 | 63 | 64 |
65 | 66 | 67 | 68 | 69 | Check out this conversation between {role1} and {role2} to discuss:
{task}
70 | {chatRef.current.length>0&&chatRef.current.map((message)=> 71 | message.role==0? 72 |
73 | {ranUser1!=null&&ranUser1>0.5?:} 74 |
75 |
76 | {message.msg==null? 77 | 78 | 79 | 80 | 81 | : 82 |

} 83 |
84 | {role1} 85 |
86 |
: 87 |
88 |
89 |
90 | {message.msg==null? 91 | 92 | 93 | 94 | 95 | : 96 |

} 97 |
98 | {role2} 99 |
100 | {ranUser2!=null&&ranUser2>0.5?:} 101 |
102 | )} 103 |
104 |
105 | 106 |
107 | 108 | 109 |
110 | 111 | setShowBanner(false)}> 112 | 113 | setShowBanner(false)} className="position-absolute top-0 end-0 me-4 mt-2">X 114 | 115 | Camel AGI - Communicative Agents on GPT | Product Hunt 116 | 117 | 118 | 119 |
120 | 121 | ) 122 | 123 | } 124 | 125 | export default AgentConvoShare; -------------------------------------------------------------------------------- /client/src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /client/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /client/src/styles/agent-convo.css: -------------------------------------------------------------------------------- 1 | .agent-convo-container{ 2 | background: #eee; 3 | } 4 | .agent-convo-box{ 5 | border-radius: 12px; 6 | background: #2b2d2f; 7 | box-shadow: 10px 10px 40px #2b2d2f; 8 | height: 80%; 9 | width: 60%; 10 | } 11 | .agent-msg-data{ 12 | color: #fff !important; 13 | background-color: transparent !important; 14 | font-family: var(--fontFamily) !important; 15 | white-space: break-spaces; 16 | font-size: 1rem !important; 17 | margin: 0 !important; 18 | overflow: hidden; 19 | padding: 0 !important; 20 | } 21 | 22 | .bubble { 23 | --r: 12px; 24 | --t: 10px; 25 | 26 | padding: calc(2*var(--r)/3); 27 | -webkit-mask: 28 | radial-gradient(var(--t) at var(--_d) 0,#0000 98%,#000 102%) 29 | var(--_d) 100%/calc(100% - var(--r)) var(--t) no-repeat, 30 | conic-gradient(at var(--r) var(--r),#000 75%,#0000 0) 31 | calc(var(--r)/-2) calc(var(--r)/-2) padding-box, 32 | radial-gradient(50% 50%,#000 98%,#0000 101%) 33 | 0 0/var(--r) var(--r) space padding-box; 34 | 35 | color: #fff; 36 | } 37 | .agent-1-chat { 38 | --_d: 0%; 39 | border-left: var(--t) solid #0000; 40 | margin-right: var(--t); 41 | box-shadow: 10px 10px 40px #2b2d2f; 42 | background: var(--themeColor) border-box; 43 | } 44 | .agent-2-chat { 45 | --_d: 100%; 46 | border-right: var(--t) solid #0000; 47 | margin-left: var(--t); 48 | box-shadow: 10px 10px 40px #2b2d2f; 49 | background: #3f65f9 border-box; 50 | } 51 | .agent-chat-icon{ 52 | min-width: 2.5rem; 53 | min-height: 2.5rem; 54 | max-width: 2.5rem; 55 | max-height: 2.5rem; 56 | 57 | } 58 | .continue-button{ 59 | background-color: #eee !important; 60 | color: #000 !important; 61 | border: none !important; 62 | border-radius: 12px !important; 63 | /* font-size: 12px !important; */ 64 | font-weight: 800 !important; 65 | } 66 | .agent-input{ 67 | background-color: transparent !important; 68 | color: #fff !important; 69 | border-top: none !important; 70 | border-left: none !important; 71 | border-right: none !important; 72 | } 73 | .agent-scroll{ 74 | overflow-y: scroll; 75 | scrollbar-width: thin; 76 | } 77 | .agent-scroll::-webkit-scrollbar { 78 | width: 0; 79 | } 80 | .scroll-container{ 81 | height: 90% !important; 82 | } 83 | .agent-msg-container>pre{ 84 | max-width: 30rem; 85 | } 86 | .key-video-agent{ 87 | width: 60%; 88 | min-height: 14rem; 89 | border-radius: 12px; 90 | } 91 | .role-name{ 92 | opacity: 60%; 93 | font-size: 12px; 94 | } 95 | .role1-container{ 96 | animation: role1msg 0.3s ease-out 0s forwards; 97 | 98 | } 99 | .role2-container{ 100 | animation: role2msg 0.3s ease-out 0s forwards; 101 | 102 | } 103 | @keyframes role1msg { 104 | 0% { 105 | margin-left: -2rem; 106 | opacity: 0; 107 | } 108 | 80% { 109 | transform: scale(1.1); 110 | } 111 | 100% { 112 | transform: scale(1); 113 | opacity: 1; 114 | } 115 | } 116 | .agent-share-btn{ 117 | opacity: 0.8; 118 | background: transparent !important; 119 | border: 1px solid white !important; 120 | padding: 0.2rem 0.4rem !important; 121 | font-size: 12px !important; 122 | } 123 | @keyframes role1msg { 124 | 0% { 125 | margin-right: -2rem; 126 | opacity: 0; 127 | } 128 | 80% { 129 | transform: scale(1.1); 130 | } 131 | 100% { 132 | transform: scale(1); 133 | opacity: 1; 134 | } 135 | } 136 | @media screen and (max-width:1000px){ 137 | .agent-convo-box{ 138 | height: 100%; 139 | width: 100%; 140 | border-radius: 0; 141 | } 142 | .agent-msg-container>pre{ 143 | max-width: 20rem; 144 | } 145 | } 146 | 147 | .logo{ 148 | width: 4rem; 149 | } -------------------------------------------------------------------------------- /client/src/styles/home.css: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css2?family=Nunito:wght@400;500;600;700;800&display=swap"); 2 | :root { 3 | 4 | --hoverColor: rgb(71, 24, 182) !important ; 5 | --fontFamily: "Nunito", sans-serif; 6 | --border: 1px solid #dfdfdf; 7 | --themeColor: #763FF9; 8 | 9 | } 10 | 11 | .powered-by{ 12 | background-color: #F6F3FF; 13 | border-radius: 22px 22px 0 0; 14 | opacity: 0.8; 15 | z-index: 99; 16 | position: fixed; 17 | bottom: 0; 18 | right: 1rem; 19 | } 20 | .banner-modal>.modal-dialog>.modal-content{ 21 | border-radius: 22px !important; 22 | } 23 | .producthunt-banner{ 24 | z-index: 99; 25 | position: fixed; 26 | top: 1.5rem; 27 | right: 1rem; 28 | } 29 | 30 | .powered-by a{ 31 | color: black; 32 | font-size: 0.8rem; 33 | } 34 | .discord-invite{ 35 | background-color: #5865f2; 36 | color: white; 37 | border-radius: 12px; 38 | text-decoration: none; 39 | } 40 | 41 | .powered-by a:hover{ 42 | color: black; 43 | text-decoration: underline !important; 44 | } 45 | 46 | .btn-filled{ 47 | background: #763FF9 !important; 48 | box-shadow: 0px 2px 25px #F0EDF9 !important; 49 | border-radius: 12px !important; 50 | border: 1px solid #763FF9 !important; 51 | color: white !important; 52 | } 53 | 54 | .btn-filled:hover{ 55 | background: var(--hoverColor) !important; 56 | 57 | } 58 | .side-nav{ 59 | width: 13.5rem ; 60 | min-height: 100vh; 61 | background: #FFFFFF; 62 | border-right: 1px solid #DFDFDF; 63 | box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.04); 64 | font-size: 0.75rem; 65 | font-weight: 700; 66 | } 67 | /* .mobile-nav{ 68 | font-size: 0.75rem !important; 69 | } */ 70 | body,html{ 71 | background-color: #ffffff !important; 72 | font-family: var(--fontFamily) !important; 73 | color:#000000 !important; 74 | } 75 | .nav-body, 76 | .nav-header > .accordion-button { 77 | padding:0.5rem 0rem !important; 78 | border:0 !important; 79 | background-color: transparent !important; 80 | color: #000 !important; 81 | font-size: 0.75rem; 82 | font-weight: 700; 83 | } 84 | .os-logo{ 85 | width: 3.75rem; 86 | height: 3.75rem; 87 | margin: 2.5rem 0; 88 | } 89 | .os-logo-mobile{ 90 | width: 2.5rem; 91 | height: 2.5rem; 92 | } 93 | .offcanvas-backdrop{ 94 | width: 100% !important; 95 | height: 100% !important; 96 | } 97 | .nav-icon{ 98 | height: 1rem; 99 | width: 1rem; 100 | margin-right: 1.5rem; 101 | } 102 | .side-accordion{ 103 | --bs-accordion-bg: transparent !important; 104 | } 105 | .nav-width{ 106 | width: 10.5rem; 107 | } 108 | .nav-width>.nav-item{ 109 | width: 100%; 110 | } 111 | 112 | .nav-header > .accordion-button::after { 113 | margin-left: auto; 114 | 115 | } 116 | .accordion-button.collapsed::after{ 117 | background-size: 1rem; 118 | color: #000 !important; 119 | margin-left: auto; 120 | } 121 | .accordion-button:not(.collapsed) { 122 | box-shadow: none !important; 123 | color: #000 !important; 124 | } 125 | .nav-header > .accordion-button:not(.collapsed)::after { 126 | transform: rotate(-180deg) !important; 127 | background-size: 1rem; 128 | color: #000 !important; 129 | } 130 | .nav-header > .accordion-button:focus { 131 | border: none !important; 132 | box-shadow: none !important; 133 | } 134 | 135 | .side-nav-links >.nav-link.active{ 136 | color: #763FF9 !important; 137 | border-radius: 1.875rem; 138 | } 139 | 140 | .side-nav-links >.nav-link{ 141 | color: #5F5B66 !important; 142 | padding: 0.375rem 2.5rem; 143 | } 144 | 145 | .side-nav-links > .active{ 146 | background-color: #F6F3FF !important; 147 | color: #763FF9 !important; 148 | } 149 | 150 | 151 | .rounded-cards{ 152 | box-sizing: border-box; 153 | background: #FFFFFF !important; 154 | border: 1px solid #DFDFDF; 155 | box-shadow: 0px 2px 25px #F0EDF9; 156 | border-radius: 22px; 157 | } 158 | 159 | .top-filters-cards{ 160 | height: 2.81rem; 161 | background: #FFFFFF !important; 162 | border: 1px solid #DFDFDF !important; 163 | box-shadow: 0px 2px 25px #F0EDF9 !important; 164 | border-radius: 0.75rem; 165 | color: #000 !important; 166 | font-size: 0.75rem !important; 167 | padding: 0.5rem 0.75rem !important; 168 | } 169 | 170 | .dropdown>.dropdown-toggle::after{ 171 | margin-left:20px !important; 172 | } 173 | 174 | .small-text{ 175 | font-size: 0.75rem !important ; 176 | } 177 | .content-container{ 178 | max-width: 50rem; 179 | } 180 | .number-text{ 181 | font-size: 1.5rem !important; 182 | font-weight: 600 !important; 183 | } 184 | 185 | .navbar-toggler:focus{ 186 | box-shadow: none; 187 | } 188 | .graph-title{ 189 | font-weight: 400; 190 | } 191 | .stats-table{ 192 | background: #FFFFFF !important; 193 | border: 1px solid #DFDFDF !important; 194 | } 195 | .stats-table>thead{ 196 | background-color: #F2F2F2; 197 | font-size: 0.75rem; 198 | } 199 | .stats-table>thead>tr>th,.stats-table>tbody>tr>td{ 200 | padding: 1.5rem; 201 | 202 | } 203 | /* .stats-table tr:first-child th:first-child { 204 | border-top-left-radius: 22px; 205 | } 206 | 207 | .stats-table tr:first-child th:last-child { 208 | border-top-right-radius: 22px; 209 | } 210 | .stats-table tr:last-child td:first-child { 211 | border-bottom-left-radius: 22px; 212 | } 213 | 214 | .stats-table tr:last-child td:last-child { 215 | border-bottom-right-radius: 22px; 216 | } */ 217 | @media screen and (max-width:992px){ 218 | .main-col{ 219 | margin-top: 7rem !important; 220 | } 221 | .nav-header > .accordion-button { 222 | font-size: 1rem; 223 | } 224 | .graph-title{ 225 | font-size: 0.9rem; 226 | } 227 | .stats-table>thead>tr>th,.stats-table>tbody>tr>td{ 228 | padding: 1rem; 229 | 230 | } 231 | .powered-by{ 232 | background-color: #21cd9c; 233 | border-radius: 0 0 12px 12px ; 234 | top: 0; 235 | right: 0; 236 | bottom: auto; 237 | } 238 | } 239 | 240 | @media screen and (min-width:1600px){ 241 | .content-container{ 242 | max-width: 75rem; 243 | } 244 | } 245 | @media screen and (max-width:500px){ 246 | .stats-table>thead>tr>th,.stats-table>tbody>tr>td{ 247 | padding: 0.5rem; 248 | 249 | } 250 | } 251 | 252 | .options-bg{ 253 | box-sizing: border-box; 254 | background: #FFFFFF !important; 255 | border: 1px solid #DFDFDF !important; 256 | box-shadow: 0px 2px 25px #F0EDF9 !important; 257 | border-radius: 50px !important; 258 | color: #000000 !important; 259 | font-size: 12px !important; 260 | } 261 | 262 | .filter-drop > button{ 263 | background-color: white !important; 264 | color: #000 !important; 265 | border: 0px !important; 266 | font-size: 12px !important; 267 | padding-left: 3px !important; 268 | padding-right: 3px !important; 269 | padding-top: 6px !important; 270 | padding-bottom: 6px !important; 271 | } 272 | .filter-drop >.dropdown-toggle::after{ 273 | content:none !important; 274 | } 275 | 276 | .filter-drop > .dropdown-menu{ 277 | font-size: 12px !important; 278 | min-width: 5rem !important; 279 | border: 1px solid #ececec!important; 280 | box-shadow: 0px 2px 25px #F0EDF9 !important; 281 | } 282 | 283 | .vr{ 284 | background-color: #acacac !important; 285 | } 286 | 287 | .icon{ 288 | width: 1.3rem ; 289 | height: 1.3rem ; 290 | cursor: pointer ; 291 | } 292 | -------------------------------------------------------------------------------- /server/agent_convo.py: -------------------------------------------------------------------------------- 1 | from database import * 2 | import urllib.parse 3 | from flask import jsonify,request,session,render_template,redirect,url_for,Blueprint 4 | from requests_oauthlib import OAuth2Session 5 | from flask_login import login_required, login_user, current_user, logout_user 6 | import secrets 7 | from datetime import datetime, date, timedelta, timezone 8 | import os, pickle, codecs 9 | from typing import List 10 | from langchain.chat_models import ChatOpenAI 11 | from langchain.prompts.chat import ( 12 | SystemMessagePromptTemplate, 13 | HumanMessagePromptTemplate, 14 | ) 15 | from langchain.schema import ( 16 | AIMessage, 17 | HumanMessage, 18 | SystemMessage, 19 | BaseMessage, 20 | ) 21 | 22 | authorization_base_url = "https://accounts.google.com/o/oauth2/v2/auth" 23 | scope = [ 24 | "https://www.googleapis.com/auth/userinfo.email", 25 | "https://www.googleapis.com/auth/userinfo.profile", 26 | "openid" 27 | ] 28 | google_client_id = os.environ['google_client_id'] 29 | google_client_secret = os.environ['google_client_secret'] 30 | word_limit = 50 # word limit for task brainstorming 31 | 32 | rp = Blueprint('rp', __name__) 33 | 34 | 35 | @rp.route("/rp/isLoggedIn", methods=['GET']) 36 | def rp_isLoggedIn(): 37 | url_host = urllib.parse.urlsplit(request.url).hostname 38 | if "5000" in request.url: 39 | redirect_uri = "http://"+url_host+":5000/rp/google_callback" 40 | else: 41 | redirect_uri = "https://"+url_host+"/rp/google_callback" 42 | google = OAuth2Session( 43 | google_client_id, scope=scope, redirect_uri=redirect_uri) 44 | login_url, state = google.authorization_url(authorization_base_url) 45 | session['oauth_state'] = google_client_id 46 | if current_user.is_authenticated: 47 | if current_user.openai_key == "" or current_user.openai_key == None: 48 | keyAdded = None 49 | else: 50 | keyAdded = current_user.openai_key 51 | return jsonify(isLoggedIn=current_user.is_authenticated,userId=current_user.id,key_added=keyAdded,image=current_user.profile_image) 52 | else: 53 | return jsonify(isLoggedIn=False,auth_url=login_url) 54 | 55 | @rp.route("/rp/google_callback", methods=['GET']) 56 | def rp_google_callback(): 57 | url_host = urllib.parse.urlsplit(request.url).hostname 58 | if "5000" in request.url: 59 | redirect_uri = "http://"+url_host+":5000/rp/google_callback" 60 | else: 61 | redirect_uri = "https://"+url_host+"/rp/google_callback" 62 | google = OAuth2Session( 63 | google_client_id, scope=scope, redirect_uri=redirect_uri) 64 | token_url = "https://www.googleapis.com/oauth2/v4/token" 65 | welcome = False 66 | try: 67 | google.fetch_token(token_url, client_secret=google_client_secret, 68 | authorization_response=request.url) 69 | except: 70 | pass 71 | response = google.get( 72 | 'https://www.googleapis.com/oauth2/v1/userinfo').json() 73 | email = response["email"].lower() 74 | googleId = str(response["id"]) 75 | name = response["name"] 76 | image = response["picture"] 77 | getAdmin = Admin.query.filter_by(email=email).first() 78 | if getAdmin == None: 79 | getAdmin = Admin(id=secrets.token_urlsafe(24), email=email,google_id=googleId, name=name,profile_image=image, created_date=datetime.now()) 80 | db.session.add(getAdmin) 81 | db.session.commit() 82 | else: 83 | getAdmin.google_id = googleId 84 | getAdmin.profile_image = image 85 | db.session.commit() 86 | login_user(getAdmin, remember=True) 87 | return redirect("http://localhost:3000/") 88 | 89 | class CAMELAgent: 90 | 91 | def __init__( 92 | self, 93 | system_message, 94 | model: ChatOpenAI, 95 | store 96 | ) -> None: 97 | self.model = model 98 | if store == None: 99 | self.system_message = system_message 100 | self.init_messages() 101 | # print("NEW") 102 | else: 103 | self.stored_messages = store 104 | self.system_message = store[0] 105 | # print("MESSAGES \n",self.stored_messages,"\n SYSTEM MESSAGE \n",self.system_message) 106 | 107 | def reset(self) -> None: 108 | self.init_messages() 109 | return self.stored_messages 110 | 111 | def init_messages(self) -> None: 112 | self.stored_messages = [self.system_message] 113 | # for msg in self.stored_messages: 114 | # print("INTIALIZED",msg.content,"\n") 115 | 116 | def update_messages(self, message: BaseMessage) -> List[BaseMessage]: 117 | self.stored_messages.append(message) 118 | # for msg in self.stored_messages: 119 | # print("UPDATED",msg.content,"\n") 120 | return self.stored_messages 121 | 122 | def step( 123 | self, 124 | input_message: HumanMessage, 125 | ) -> AIMessage: 126 | messages = self.update_messages(input_message) 127 | output_message = self.model(messages) 128 | self.update_messages(output_message) 129 | 130 | return output_message 131 | 132 | def store_messages(self) -> None: 133 | return self.stored_messages 134 | 135 | 136 | 137 | 138 | def starting_convo(assistant_role_name,user_role_name,task): 139 | task_specifier_sys_msg = SystemMessage(content="You can make a task more specific.") 140 | task_specifier_prompt = ( 141 | """Here is a task that {assistant_role_name} will help {user_role_name} to complete: {task}. 142 | Please make it more specific. Be creative and imaginative. 143 | Please reply with the specified task in {word_limit} words or less. Do not add anything else.""" 144 | ) 145 | task_specifier_template = HumanMessagePromptTemplate.from_template(template=task_specifier_prompt) 146 | task_specify_agent = CAMELAgent(task_specifier_sys_msg, ChatOpenAI(temperature=1.0),None) 147 | task_specifier_msg = task_specifier_template.format_messages(assistant_role_name=assistant_role_name, 148 | user_role_name=user_role_name, 149 | task=task, word_limit=word_limit)[0] 150 | specified_task_msg = task_specify_agent.step(task_specifier_msg) 151 | # print(f"Specified task: {specified_task_msg.content}") 152 | specified_task = specified_task_msg.content 153 | 154 | assistant_inception_prompt = ( 155 | """Never forget you are a {assistant_role_name} and I am a {user_role_name}. Never flip roles! Never instruct me! 156 | We share a common interest in collaborating to successfully complete a task. 157 | You must help me to complete the task. 158 | Here is the task: {task}. Never forget our task! 159 | I must instruct you based on your expertise and my needs to complete the task. 160 | 161 | I must give you one instruction at a time. 162 | You must write a specific solution that appropriately completes the requested instruction. 163 | You must decline my instruction honestly if you cannot perform the instruction due to physical, moral, legal reasons or your capability and explain the reasons. 164 | Do not add anything else other than your solution to my instruction. 165 | You are never supposed to ask me any questions you only answer questions. 166 | You are never supposed to reply with a flake solution. Explain your solutions. 167 | Your solution must be declarative sentences and simple present tense. 168 | Unless I say the task is completed, you should always start with: 169 | 170 | Solution: 171 | 172 | should be specific and provide preferable implementations and examples for task-solving. 173 | Always end with: Next request.""" 174 | ) 175 | 176 | user_inception_prompt = ( 177 | """Never forget you are a {user_role_name} and I am a {assistant_role_name}. Never flip roles! You will always instruct me. 178 | We share a common interest in collaborating to successfully complete a task. 179 | I must help you to complete the task. 180 | Here is the task: {task}. Never forget our task! 181 | You must instruct me based on my expertise and your needs to complete the task ONLY in the following two ways: 182 | 183 | 1. Instruct with a necessary input: 184 | Instruction: 185 | Input: 186 | 187 | 2. Instruct without any input: 188 | Instruction: 189 | Input: None 190 | 191 | The "Instruction" describes a task or question. The paired "Input" provides further context or information for the requested "Instruction". 192 | 193 | You must give me one instruction at a time. 194 | I must write a response that appropriately completes the requested instruction. 195 | I must decline your instruction honestly if I cannot perform the instruction due to physical, moral, legal reasons or my capability and explain the reasons. 196 | You should instruct me not ask me questions. 197 | Now you must start to instruct me using the two ways described above. 198 | Do not add anything else other than your instruction and the optional corresponding input! 199 | Keep giving me instructions and necessary inputs until you think the task is completed. 200 | When the task is completed, you must only reply with a single word . 201 | Never say unless my responses have solved your task.""" 202 | ) 203 | return specified_task,assistant_inception_prompt,user_inception_prompt 204 | 205 | def get_sys_msgs(assistant_role_name: str, user_role_name: str, task: str,assistant_inception_prompt,user_inception_prompt): 206 | 207 | assistant_sys_template = SystemMessagePromptTemplate.from_template(template=assistant_inception_prompt) 208 | assistant_sys_msg = assistant_sys_template.format_messages(assistant_role_name=assistant_role_name, user_role_name=user_role_name, task=task)[0] 209 | 210 | user_sys_template = SystemMessagePromptTemplate.from_template(template=user_inception_prompt) 211 | user_sys_msg = user_sys_template.format_messages(assistant_role_name=assistant_role_name, user_role_name=user_role_name, task=task)[0] 212 | 213 | return assistant_sys_msg, user_sys_msg 214 | 215 | @rp.route("/rp/start", methods=['POST']) 216 | def start_rp(): 217 | if not current_user.is_authenticated: 218 | return redirect("/agent_convo") 219 | os.environ["OPENAI_API_KEY"] = current_user.openai_key 220 | assistant_role_name = request.json["role1"] 221 | user_role_name = request.json["role2"] 222 | task = request.json["task"] 223 | sessId = request.json["sessId"] 224 | if sessId == 0: 225 | getSession = Agent_Session(role_1=assistant_role_name,role_2=user_role_name,task=task,admin_id=current_user.id) 226 | db.session.add(getSession) 227 | db.session.commit() 228 | specified_task,assistant_inception_prompt,user_inception_prompt = starting_convo(assistant_role_name, user_role_name, task) 229 | assistant_sys_msg, user_sys_msg = get_sys_msgs(assistant_role_name, user_role_name, specified_task,assistant_inception_prompt,user_inception_prompt) 230 | assistant_agent = CAMELAgent(assistant_sys_msg, ChatOpenAI(temperature=0.2),None) 231 | user_agent = CAMELAgent(user_sys_msg, ChatOpenAI(temperature=0.2),None) 232 | # Reset agents 233 | assistant_agent.reset() 234 | user_agent.reset() 235 | 236 | # Initialize chats 237 | assistant_msg = HumanMessage( 238 | content=(f"{user_sys_msg.content}. " 239 | "Now start to give me introductions one by one. " 240 | "Only reply with Instruction and Input.")) 241 | 242 | user_msg = HumanMessage(content=f"{assistant_sys_msg.content}") 243 | user_msg = assistant_agent.step(user_msg) 244 | else: 245 | getSession = Agent_Session.query.filter_by(id=sessId).first() 246 | user_store = pickle.loads(codecs.decode((getSession.user_store).encode(), "base64")) 247 | assistant_store = pickle.loads(codecs.decode((getSession.assistant_store).encode(), "base64")) 248 | user_agent = CAMELAgent(None, ChatOpenAI(temperature=0.2),user_store) 249 | assistant_agent = CAMELAgent(None, ChatOpenAI(temperature=0.2),assistant_store) 250 | assistant_msg = HumanMessage( 251 | content=(f"{assistant_store[-1].content}")) 252 | 253 | # chat_turn_limit, n = 10, 0 254 | # while n < chat_turn_limit: 255 | # n += 1 256 | user_ai_msg = user_agent.step(assistant_msg) 257 | user_msg = HumanMessage(content=user_ai_msg.content) 258 | userMsg = user_msg.content.replace("Instruction: ","").replace("Input: None","").replace("Input: None.","") 259 | # print(f"AI User ({user_role_name}):\n\n{user_msg.content}\n\n") 260 | assistant_ai_msg = assistant_agent.step(user_msg) 261 | assistant_msg = HumanMessage(content=assistant_ai_msg.content) 262 | assistantMsg = assistant_msg.content.replace("Solution: ","").replace("Next request.","") 263 | # print(f"AI Assistant ({assistant_role_name}):\n\n{assistant_msg.content}\n\n") 264 | convoEnd = False 265 | if "" in user_msg.content: 266 | convoEnd = True 267 | getUserStore = user_agent.store_messages() 268 | getSession.user_store = codecs.encode(pickle.dumps(getUserStore), "base64").decode() 269 | getAssistantStore = assistant_agent.store_messages() 270 | getSession.assistant_store = codecs.encode(pickle.dumps(getAssistantStore), "base64").decode() 271 | db.session.commit() 272 | return jsonify(sessId=getSession.id,userMsg=userMsg,assistantMsg=assistantMsg,convoEnd=convoEnd) 273 | 274 | 275 | @rp.route("/rp/get_chat", methods=['get']) 276 | def rp_get_chat(): 277 | sessId = request.args.get('sessId') 278 | getSession = Agent_Session.query.filter_by(id=sessId).first() 279 | assistant_store = pickle.loads(codecs.decode((getSession.assistant_store).encode(), "base64")) 280 | messages = [] 281 | for store in assistant_store[2:]: 282 | if str(type(store)) == "": 283 | messages.append({"role":0,"msg":store.content.replace("Instruction: ","").replace("Input: None","").replace("Input: None.","")}) 284 | elif str(type(store)) == "": 285 | messages.append({"role":1,"msg":store.content.replace("Solution: ","").replace("Next request.","")}) 286 | return jsonify(role1=getSession.role_1,role2=getSession.role_2,task=getSession.task,messages=messages) 287 | -------------------------------------------------------------------------------- /server/database.py: -------------------------------------------------------------------------------- 1 | from flask_sqlalchemy import SQLAlchemy 2 | from sqlalchemy import DateTime, ForeignKey, MetaData 3 | from flask_login import UserMixin 4 | 5 | from flask import Flask 6 | 7 | convention = { 8 | "ix": 'ix_%(column_0_label)s', 9 | "uq": "uq_%(table_name)s_%(column_0_name)s", 10 | "ck": "ck_%(table_name)s_%(constraint_name)s", 11 | "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s", 12 | "pk": "pk_%(table_name)s" 13 | } 14 | 15 | metadata = MetaData(naming_convention=convention) 16 | db = SQLAlchemy(metadata=metadata) 17 | app = Flask(__name__) 18 | 19 | class Agent_Session(db.Model): 20 | __tablename__ = "agent_session" 21 | id = db.Column(db.Integer, primary_key=True, autoincrement=True) 22 | role_1 = db.Column(db.String(200), default="", server_default = "") 23 | role_2 = db.Column(db.String(200), default="", server_default = "") 24 | task = db.Column(db.String(3000), default="", server_default = "") 25 | user_store = db.Column(db.String, default="", server_default = "") 26 | assistant_store = db.Column(db.String, default="", server_default = "") 27 | admin_id = db.Column(db.String(100), ForeignKey("admin.id"), index=True) 28 | 29 | class Admin(UserMixin,db.Model): 30 | __tablename__ = "admin" 31 | id = db.Column(db.String(100), primary_key=True) 32 | name = db.Column(db.String(100)) 33 | email = db.Column(db.String(100), unique=True, index=True) 34 | google_id = db.Column(db.String(100)) 35 | openai_key = db.Column(db.String(100)) 36 | profile_image = db.Column(db.String(100000)) 37 | password = db.Column(db.String(100)) 38 | created_date = db.Column(DateTime) 39 | gpt_model = db.Column(db.String, default="gpt-3.5-turbo", server_default="gpt-3.5-turbo") 40 | agent_sessions = db.relationship('Agent_Session', backref='admin', 41 | cascade="all,delete", lazy='dynamic') 42 | def get_id(self): 43 | return (self.id) -------------------------------------------------------------------------------- /server/requirements.txt: -------------------------------------------------------------------------------- 1 | aiohttp==3.8.4 2 | aiosignal==1.3.1 3 | alembic==1.10.4 4 | async-timeout==4.0.2 5 | attrs==23.1.0 6 | blinker==1.6.2 7 | certifi==2022.12.7 8 | charset-normalizer==3.1.0 9 | click==8.1.3 10 | colorama==0.4.6 11 | dataclasses-json==0.5.7 12 | Flask==2.3.1 13 | Flask-Login==0.6.2 14 | Flask-Migrate==4.0.4 15 | Flask-SQLAlchemy==3.0.3 16 | frozenlist==1.3.3 17 | greenlet==2.0.2 18 | idna==3.4 19 | importlib-metadata==6.6.0 20 | importlib-resources==5.12.0 21 | itsdangerous==2.1.2 22 | Jinja2==3.1.2 23 | langchain==0.0.152 24 | Mako==1.2.4 25 | MarkupSafe==2.1.2 26 | marshmallow==3.19.0 27 | marshmallow-enum==1.5.1 28 | multidict==6.0.4 29 | mypy-extensions==1.0.0 30 | numexpr==2.8.4 31 | numpy==1.24.3 32 | oauthlib==3.2.2 33 | openai==0.27.5 34 | openapi-schema-pydantic==1.2.4 35 | packaging==23.1 36 | pydantic==1.10.7 37 | PyYAML==6.0 38 | requests==2.29.0 39 | requests-oauthlib==1.3.1 40 | SQLAlchemy==2.0.11 41 | tenacity==8.2.2 42 | tqdm==4.65.0 43 | typing-extensions==4.5.0 44 | typing-inspect==0.8.0 45 | urllib3==1.26.15 46 | Werkzeug==2.3.1 47 | yarl==1.9.2 48 | zipp==3.15.0 49 | -------------------------------------------------------------------------------- /server/webserver.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | from flask_migrate import Migrate 3 | from database import * 4 | import os 5 | import urllib.parse 6 | from flask import jsonify,request,session,render_template,redirect,url_for,Blueprint 7 | from requests_oauthlib import OAuth2Session 8 | from flask_login import UserMixin, LoginManager, login_required, login_user, current_user, logout_user 9 | import secrets 10 | from datetime import datetime, date, timedelta, timezone 11 | import os 12 | import json 13 | import random 14 | import requests 15 | from agent_convo import rp 16 | 17 | try: 18 | import config 19 | except ModuleNotFoundError: 20 | pass 21 | 22 | 23 | app = Flask(__name__) 24 | app.register_blueprint(rp) 25 | app.secret_key = 'autogptsamurai@123' 26 | 27 | app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///./test.db' 28 | db.init_app(app) 29 | db.app = app 30 | migrate = Migrate(app, db, compare_type=True, 31 | render_as_batch=True) 32 | 33 | login_manager = LoginManager(app) 34 | 35 | 36 | @login_manager.user_loader 37 | def load_user(user_id): 38 | return Admin.query.filter_by(id=user_id).first() 39 | 40 | os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1' 41 | 42 | @app.route("/change_model", methods=['POST']) 43 | def change_model(): 44 | model = request.values["model"] 45 | current_user.gpt_model = model 46 | db.session.commit() 47 | return "Success" 48 | 49 | @app.route("/logout", methods=['GET']) 50 | def logout(): 51 | logout_user() 52 | return "Success", 200 53 | 54 | @app.route("/store_key", methods=['POST']) 55 | def store_key(): 56 | key = request.json['key'] 57 | getAdmin = Admin.query.filter_by(id=current_user.id).first() 58 | if len(key) == 51: 59 | getAdmin.openai_key = key 60 | db.session.commit() 61 | return jsonify(True) 62 | else: 63 | return jsonify(False), 400 64 | 65 | if __name__ == '__main__': 66 | app.run(host="0.0.0.0", debug=True) 67 | -------------------------------------------------------------------------------- /steps_to_run.md: -------------------------------------------------------------------------------- 1 | # Server 2 | 3 | 1. To run server, install virtualenv first https://virtualenv.pypa.io/en/latest/ and create a new virtual environment to load all necessary python packages 4 | 5 | 2. Go to server folder and install all necessary packages using command "pip install -r requirements.txt" 6 | 7 | 3. Set environment variables FLASK_ENV=dev and FLASK_APP=webserver.py 8 | 9 | 4. Create a db for storing all the info using commands i) flask db init ii) flask db migrate iii) flask db upgrade 10 | 11 | 5. Run the server using python webserver.py 12 | 13 | 14 | # Client 15 | 16 | 1. To run client, go to client folder and do npm install 17 | 18 | 2. Now run "npm start" and this should start the client 19 | --------------------------------------------------------------------------------