You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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 /chat route 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() and print() 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

火山引擎 最新活动