Flask聊天Bot部署Google Cloud Shell遇EOFError,求Web交互改造方案
Hey there! The issue here is super clear—your current code uses input() and print() which are built for command-line interactive sessions, but when deployed to App Engine, you're running a web app that follows an HTTP request/response cycle instead of a terminal. That's exactly why you're hitting the EOFError—there's no terminal to read input from once your app is live on the web.
Let's fix this by restructuring your app to work as a proper web-based chat interface. Here's how to do it step by step:
1. Refactor the Backend: Build a Chat API
First, we'll rewrite your chat logic to accept user input as an HTTP request and return the bot's response, instead of relying on terminal input/output. We'll also add a route to serve a simple chat UI for your team to interact with.
Here's the updated Flask code:
from flask import Flask, request, render_template_string import pandas as pd import gspread from oauth2client.service_account import ServiceAccountCredentials from sklearn.svm import SVC from sklearn.model_selection import train_test_split as tts from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.preprocessing import LabelEncoder as LE from sklearn.metrics.pairwise import cosine_similarity import nltk nltk.download('punkt') from nltk.stem.lancaster import LancasterStemmer # ---------------------- # Load Model & Data Once (at app startup) # ---------------------- scope = ['https://spreadsheets.google.com/feeds','https://www.googleapis.com/auth/drive'] credentials = ServiceAccountCredentials.from_json_keyfile_name('bot-1234.json', scope) gc = gspread.authorize(credentials) faq = pd.DataFrame(gc.open('Data Gathering').worksheet('Sheet1').get_all_records()) stemmer = LancasterStemmer() def cleanup(sentence): word_tok = nltk.word_tokenize(sentence) stemmed_words = [stemmer.stem(w) for w in word_tok] return ' '.join(stemmed_words) le = LE() tfv = TfidfVectorizer(min_df=1, stop_words='english') questions = faq['Questions'].values X = [] for question in questions: X.append(cleanup(question)) tfv.fit(X) le.fit(faq['Class']) X = tfv.transform(X) y = le.transform(faq['Class']) trainx, testx, trainy, testy = tts(X, y, test_size=.25, random_state=42) model = SVC(kernel='linear') model.fit(trainx, trainy) print("SVC:", model.score(testx, testy)) def get_max5(arr): ixarr = [] for ix, el in enumerate(arr): ixarr.append((el, ix)) ixarr.sort() ixs = [] for i in ixarr[-5:]: ixs.append(i[1]) return ixs[::-1] # ---------------------- # Flask App Setup # ---------------------- app = Flask(__name__) # Simple HTML chat UI template CHAT_UI = """ <!DOCTYPE html> <html> <head> <title>Bot Assistant</title> <style> .chat-container { max-width: 800px; margin: 2rem auto; padding: 1rem; font-family: Arial, sans-serif; } .message { margin: 1rem 0; padding: 1rem; border-radius: 8px; } .user-message { background-color: #e3f2fd; text-align: right; } .bot-message { background-color: #f5f5f5; } .input-area { margin-top: 2rem; display: flex; gap: 1rem; } #user-input { flex: 1; padding: 1rem; font-size: 1rem; border: 1px solid #ddd; border-radius: 4px; } #send-btn { padding: 1rem 2rem; font-size: 1rem; background-color: #2196f3; color: white; border: none; border-radius: 4px; cursor: pointer; } #send-btn:hover { background-color: #1976d2; } </style> </head> <body> <div class="chat-container"> <h2>Bot - The Assistant</h2> <div id="chat-history"> <div class="message bot-message">Hi, Welcome to BOT - The Assistant!</div> </div> <div class="input-area"> <input type="text" id="user-input" placeholder="Type your question here..."> <button id="send-btn">Send</button> </div> </div> <script> const chatHistory = document.getElementById('chat-history'); const userInput = document.getElementById('user-input'); const sendBtn = document.getElementById('send-btn'); function sendMessage() { const message = userInput.value.trim(); if (!message) return; // Add user message to chat history const userMsgDiv = document.createElement('div'); userMsgDiv.className = 'message user-message'; userMsgDiv.textContent = message; chatHistory.appendChild(userMsgDiv); // Clear input field userInput.value = ''; // Send request to backend API fetch('/chat', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ message: message }) }) .then(response => response.json()) .then(data => { // Add bot response to chat history const botMsgDiv = document.createElement('div'); botMsgDiv.className = 'message bot-message'; botMsgDiv.textContent = data.response; chatHistory.appendChild(botMsgDiv); // Scroll to bottom of chat chatHistory.scrollTop = chatHistory.scrollHeight; }) .catch(error => console.error('Error sending message:', error)); } // Add event listeners for send button and enter key sendBtn.addEventListener('click', sendMessage); userInput.addEventListener('keypress', (e) => { if (e.key === 'Enter') sendMessage(); }); </script> </body> </html> """ @app.route('/') def index(): # Serve the chat UI when users visit the root URL return render_template_string(CHAT_UI) @app.route('/chat', methods=['POST']) def chat(): # Get user message from JSON request data = request.get_json() usr_msg = data.get('message', '').strip().lower() # Handle simple shortcut commands if usr_msg in ('q','quit','end','e') : return {'response': "It was good to be of help."} if usr_msg == 'yes': return {'response': "Yes!"} if usr_msg == 'no': return {'response': "No?"} # Core chat logic (adapted from your original code) t_usr = tfv.transform([cleanup(usr_msg)]) class_ = le.inverse_transform(model.predict(t_usr)) questionset = faq[faq['Class']==class_[0]] cos_sims = [] for question in questionset['Questions']: sims = cosine_similarity(tfv.transform([question]), t_usr) cos_sims.append(sims) ind = cos_sims.index(max(cos_sims)) # Return the bot's answer as JSON bot_response = faq['Answer'][questionset.index[ind]] return {'response': bot_response} if __name__ == '__main__': app.run(host='0.0.0.0', port=8080, debug=True)
2. Update Your Dependencies
Your Flask version is quite outdated (0.11.1), which could cause compatibility issues with newer libraries. Update your requirements.txt to use more recent stable versions:
Flask>=2.3.3 gunicorn>=21.2.0 gspread>=5.10.0 oauth2client==4.1.3 PyOpenSSL>=23.2.0 numpy>=1.24.3 scikit-learn>=1.3.0 scipy>=1.11.3 nltk>=3.8.1 pandas>=2.1.1
3. Key Changes Explained
- Model Loading: We moved all model/data loading code to run once when the app starts, instead of on every request—this makes your app much faster.
- Web UI: The
/route serves a clean, responsive chat interface where users can type messages and see bot replies in real-time. - Chat API: The
/chatroute is a POST endpoint that accepts user messages as JSON, runs your chat logic, and returns the bot's response as JSON. - Removed Terminal Code: We got rid of all
input()andprint()calls since they don't work in web environments.
4. Redeploy Your App
After making these changes, redeploy to App Engine Flex. Now your team members can access the web link, type questions in the UI, and interact with the bot just like they would in the terminal—but through a proper, shareable web interface.
内容的提问来源于stack exchange,提问作者India.Rocket




