Creating an AI chatbot using CopilotKit integrated with a Flask backend can be an exciting project. Below is a step-by-step guide on how to set up your project, including the necessary components for both the frontend (using React and CopilotKit) and the backend (using Flask).
First, create a virtual environment and install Flask:
mkdir chatbot-backend cd chatbot-backend python -m venv venv source venv/bin/activate # On Windows use `venv\Scripts\activate` pip install Flask flask-cors
Create a file named app.py:
from flask import Flask, request, jsonify from flask_cors import CORS import openai # Make sure to install OpenAI SDK if you're using it app = Flask(__name__) CORS(app) # Allow CORS for all domains # Set your OpenAI API key openai.api_key = 'YOUR_OPENAI_API_KEY' @app.route('/api/chat', methods=['POST']) def chat(): user_message = request.json.get('message') # Call the AI model (e.g., OpenAI GPT) response = openai.ChatCompletion.create( model="gpt-3.5-turbo", messages=[{"role": "user", "content": user_message}] ) bot_message = response.choices[0].message['content'] return jsonify({'response': bot_message}) if __name__ == '__main__': app.run(debug=True)
Run your Flask app:
python app.py
Your backend should now be running on http://127.0.0.1:5000.
In a new directory, create your React app:
npx create-react-app chatbot-frontend cd chatbot-frontend
Install CopilotKit and Axios for making API calls:
npm install @copilotkit/react axios
Create a file named Chatbot.js in the src directory:
import React, { useState, useEffect } from 'react'; import axios from 'axios'; import { CopilotSidebar, useCopilotChat } from '@copilotkit/react'; import './Chatbot.css'; // Importing CSS file for styling const Chatbot = () => { const [message, setMessage] = useState(''); const [chatHistory, setChatHistory] = useState([]); const [selectedPrompt, setSelectedPrompt] = useState(''); const [conversations, setConversations] = useState([]); const [prompts, setPrompts] = useState([]); const [newPrompt, setNewPrompt] = useState(''); const [searchTerm, setSearchTerm] = useState(''); const [showPromptInput, setShowPromptInput] = useState(false); // State to toggle prompt input visibility const { addMessage } = useCopilotChat(); useEffect(() => { // Load conversations and prompts from local storage on component mount const storedChats = JSON.parse(localStorage.getItem('chatHistory')) || []; const storedPrompts = JSON.parse(localStorage.getItem('prompts')) || []; setConversations(storedChats); setPrompts(storedPrompts); // Load the most recent conversation into chat history if available if (storedChats.length > 0) { setChatHistory(storedChats[storedChats.length - 1].history); } }, []); const handleSendMessage = async () => { const userMessage = { sender: 'User', text: message }; const updatedChatHistory = [...chatHistory, userMessage]; setChatHistory(updatedChatHistory); setMessage(''); try { const response = await axios.post('http://127.0.0.1:5000/api/chat', { message }); const botMessage = { sender: 'Bot', text: response.data.response }; updatedChatHistory.push(botMessage); setChatHistory(updatedChatHistory); // Add messages to Copilot addMessage(userMessage); addMessage(botMessage); // Save updated chat history to local storage localStorage.setItem('chatHistory', JSON.stringify(updatedChatHistory)); } catch (error) { console.error('Error sending message:', error); } }; const handlePromptSelect = (prompt) => { setSelectedPrompt(prompt); setMessage(prompt); }; const handleConversationClick = (conversation) => { setChatHistory(conversation.history); }; const handleSaveConversation = () => { const title = prompt("Enter a title for this conversation:"); if (title) { const newConversation = { title, history: chatHistory }; const updatedConversations = [...conversations, newConversation]; setConversations(updatedConversations); localStorage.setItem('chatHistory', JSON.stringify(updatedConversations)); } }; const handleAddPrompt = () => { if (newPrompt.trim()) { const updatedPrompts = [...prompts, newPrompt.trim()]; setPrompts(updatedPrompts); localStorage.setItem('prompts', JSON.stringify(updatedPrompts)); setNewPrompt(''); setShowPromptInput(false); // Hide the input after adding } }; // Function to delete a conversation const handleDeleteConversation = (index) => { const updatedConversations = conversations.filter((_, i) => i !== index); setConversations(updatedConversations); localStorage.setItem('chatHistory', JSON.stringify(updatedConversations)); // Optionally reset chat history if the deleted conversation was currently loaded if (chatHistory === conversations[index].history) { setChatHistory([]); } }; // Filtered prompts based on search term const filteredPrompts = prompts.filter(prompt => prompt.toLowerCase().includes(searchTerm.toLowerCase()) ); // Filtered conversations based on search term const filteredConversations = conversations.filter(conversation => conversation.title.toLowerCase().includes(searchTerm.toLowerCase()) ); return ( <div className="chatbot-container"> <CopilotSidebar title="Recent Conversations"> <input type="text" placeholder="Search Conversations..." value={searchTerm} onChange={(e) => setSearchTerm(e.target.value)} className="search-input" /> {filteredConversations.map((conversation, index) => ( <div key={index} className="conversation-title"> <span onClick={() => handleConversationClick(conversation)}> {conversation.title} </span> <button className="delete-button" onClick={() => handleDeleteConversation(index)}> ?️ {/* Delete icon */} </button> </div> ))} <button onClick={handleSaveConversation} className="save-button">Save Conversation</button> </CopilotSidebar> <div className="chat-area"> <h2>AI Chatbot</h2> <div className="chat-history"> {chatHistory.map((chat, index) => ( <div key={index} className={`message ${chat.sender === 'User' ? 'user' : 'bot'}`}> <strong>{chat.sender}:</strong> {chat.text} </div> ))} </div> <div className="input-area"> <select value={selectedPrompt} onChange={(e) => handlePromptSelect(e.target.value)} className="prompt-select" > <option value="">Select a prompt...</option> {filteredPrompts.map((prompt, index) => ( <option key={index} value={prompt}>{prompt}</option> ))} </select> {/* Button to toggle visibility of the new prompt input */} <button onClick={() => setShowPromptInput(!showPromptInput)} className="toggle-prompt-button"> {showPromptInput ? "Hide Prompt Input" : "Add New Prompt"} </button> {/* New Prompt Input Field */} {showPromptInput && ( <input type="text" value={newPrompt} onChange={(e) => setNewPrompt(e.target.value)} placeholder="Add a new prompt..." className="new-prompt-input" /> )} {/* Button to add the new prompt */} {showPromptInput && ( <button onClick={handleAddPrompt} className="add-prompt-button">Add Prompt</button> )} {/* Message Input Field */} <input type="text" value={message} onChange={(e) => setMessage(e.target.value)} placeholder="Type your message..." className="message-input" /> <button onClick={handleSendMessage} className="send-button">Send</button> </div> </div> </div> ); }; export default Chatbot;
Replace the contents of src/App.js with:
import React from 'react'; import Chatbot from './Chatbot'; function App() { return ( <div className="App"> <Chatbot /> </div> ); } export default App;
.chatbot-container { display: flex; height: 100vh; } .chat-area { margin-left: 20px; flex-grow: 1; padding: 20px; background-color: #f9f9f9; border-radius: 8px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); } .chat-history { border: 1px solid #ccc; padding: 10px; height: calc(100% - 120px); /* Adjust height based on input area */ overflow-y: scroll; border-radius: 8px; } .message { margin-bottom: 10px; } .user { text-align: right; } .bot { text-align: left; } .input-area { display: flex; align-items: center; } .prompt-select { margin-right: 10px; } .message-input { flex-grow: 1; padding: 10px; border-radius: 4px; border: 1px solid #ccc; } .send-button { padding: 10px 15px; background-color: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer; } .send-button:hover { background-color: #0056b3; } .conversation-title { padding: 10px; cursor: pointer; } .conversation-title:hover { background-color: #f0f0f0; } .save-button { margin-top: 10px; padding: 5px 10px; background-color: #28a745; color: white; border: none; border-radius: 4px; cursor: pointer; } .save-button:hover { background-color: #218838; } .prompt-select, .new-prompt-input, .message-input { margin-right: 10px; } .search-input { margin-bottom: 10px; } .new-prompt-input { flex-grow: 1; /* Allow it to take remaining space */ padding: 10px; border-radius: 4px; border: 1px solid #ccc; } .add-prompt-button, .send-button, .save-button { padding: 10px 15px; background-color: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer; } .add-prompt-button:hover, .send-button:hover, .save-button:hover { background-color: #0056b3; /* Darker shade for hover */ } .conversation-title { padding: 10px; cursor: pointer; } .conversation-title:hover { background-color: #f0f0f0; /* Highlight on hover */ } .toggle-prompt-button { margin-right: 10px; padding: 10px 15px; background-color: #17a2b8; /* Different color for visibility */ color: white; border: none; border-radius: 4px; cursor: pointer; } .toggle-prompt-button:hover { background-color: #138496; /* Darker shade for hover */ }
Start your React app:
npm start
Your frontend should now be running on http://localhost:3000.
To include a GitHub repository URL in your dev.to post about building a chatbot with CopilotKit, Flask, and React, you can format it as follows:
In this post, we'll walk through the steps to create an interactive AI chatbot using CopilotKit for the frontend, Flask as the backend, and React for the user interface.
You can find the complete code for this project on GitHub: Chatbot with CopilotKit
You now have a basic AI chatbot built using CopilotKit for the frontend and Flask for the backend! You can enhance this project by adding features like user authentication, saving chat history, or improving UI/UX design.
The above is the detailed content of Creating an AI Chatbot with CopilotKit: A Step-by-Step Guide Using Flask and React. For more information, please follow other related articles on the PHP Chinese website!