You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Python Spacy开发的ChatBot集成到不支持Python的Web站点?

问题描述

我用Python和Spacy开发了一款ChatBot,已完成HTML交互界面,计划集成到我的HTML+JavaScript站点中。但我的Web服务器不支持Python,尝试将Python代码转译为JavaScript(涉及NLP、TensorFlow等技术)后,无法实现原Python版本的功能效果。

附原Python代码:

import spacy
import random

# load NLP model
nlp = spacy.load("en_core_news_sm")
nlp.max_length = 10000000

# load text from file
with open("deutsch_corpus.txt", encoding='utf-8') as f:
    text = f.read()

# parse text with NLP model
doc = nlp(text)

# define function to generate bot response
def generate_response(user_input):
    # parse user input with NLP model
    user_doc = nlp(user_input)

    # check if the user input contains information that should be stored
    remember = False
    remember_text = ""
    for sent in user_doc.sents:
        if any(word in sent.text.lower() for word in ["I am", "my friend", "my girlfriend", "I was", "I have", "I have", "my mother is", "my mother is", "I would be", "I find", "my name is"]):
            remember = True
            remember_text = sent.text
            break

    # If the user input contains information to remember, store it in the memory file
    if remember:
        remember_text = remember_text.lower()
        with open("german_corpus.txt", "a", encoding='utf-8') as f:
            f.write(remember_text.replace("ich bin", "Du bist").replace("mein", "Dein").replace("meine", "Deine").replace("meine mutter ist", "deine Mutter ist").replace("meine freundin ist", "deine Freundin ist"). replace("would have", "would have").replace("have", "have").replace("have", "have").replace("I would be", "you would be").replace("I find", "you find").replace("my name", "your name is").replace("my name is", "your name is") + "\n")
        return "Ok, I'll remember that!"

    # search for sentences in the corpus that are similar to the user input
    similarity_scores = []
    for sentence in doc.sents:
        score = sentence.similarity(user_doc)
        similarity_scores.append((sentence, score))

    # sort sentences by similarity score
    similarity_scores.sort(key=lambda x: x[1], reverse=True)

    # if no similar sentence is found, a random answer is returned
    if similarity_scores[0][1] < 0.5:
        return "Sorry, I don't understand."

    # Return most similar sentence as bot response.
    return similarity_scores[0][0].text

附原HTML代码:

<!DOCTYPE html>
<html lang="de">
<head>
    <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>TalkyAI</title>
</head>
<body>
    <header>
        <nav>
            <ul>
                <li><a href="#">KI trainieren</a></li>
                <li><a href="#" class="active">Chat</a></li>
                <li><a href="#">Account</a></li>
            </ul>
            <div class="logout-btn"><a href="#">Abmelden</a></div>
        </nav>
    </header>
    <main>
        <div id="chat-container">
            <div id="chat-output"></div>
            <div id="chat-input">
                <input type="text" id="message-input" placeholder="Gib deine Nachricht ein...">
                <button id="send-btn">Senden</button>
            </div>
        </div>
    </main>
    <script>

    </script>
</body>
</html>

解决方案

方案1:部署Python后端服务(推荐,保留原功能效果)

直接转译JS会丢失NLP模型的精度,建议将Python逻辑封装为后端接口,前端通过AJAX调用。

步骤1:将Python代码改造为Flask接口

from flask import Flask, request, jsonify
from flask_cors import CORS
import spacy

app = Flask(__name__)
CORS(app)  # 解决跨域问题

# 加载NLP模型
nlp = spacy.load("en_core_news_sm")
nlp.max_length = 10000000

# 加载语料库
with open("deutsch_corpus.txt", encoding='utf-8') as f:
    text = f.read()
doc = nlp(text)

@app.route('/chat', methods=['POST'])
def chat():
    user_input = request.json.get('message', '')
    user_doc = nlp(user_input)

    # 处理记忆逻辑
    remember = False
    remember_text = ""
    trigger_phrases = ["i am", "my friend", "my girlfriend", "i was", "i have", "my mother is", "i would be", "i find", "my name is"]
    for sent in user_doc.sents:
        if any(phrase in sent.text.lower() for phrase in trigger_phrases):
            remember = True
            remember_text = sent.text
            break

    if remember:
        remember_text = remember_text.lower()
        # 替换人称并写入文件
        replaced_text = remember_text.replace("ich bin", "Du bist")\
                                     .replace("mein", "Dein")\
                                     .replace("meine", "Deine")\
                                     .replace("meine mutter ist", "deine Mutter ist")\
                                     .replace("meine freundin ist", "deine Freundin ist")\
                                     .replace("i would be", "you would be")\
                                     .replace("i find", "you find")\
                                     .replace("my name is", "your name is")
        with open("german_corpus.txt", "a", encoding='utf-8') as f:
            f.write(replaced_text + "\n")
        return jsonify({"response": "Ok, I'll remember that!"})

    # 计算句子相似度
    similarity_scores = []
    for sentence in doc.sents:
        score = sentence.similarity(user_doc)
        similarity_scores.append((sentence.text, score))
    
    similarity_scores.sort(key=lambda x: x[1], reverse=True)

    if similarity_scores[0][1] < 0.5:
        return jsonify({"response": "Sorry, I don't understand."})
    
    return jsonify({"response": similarity_scores[0][0]})

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

步骤2:修改前端JS调用接口

在HTML的<script>标签中添加以下代码:

const sendBtn = document.getElementById('send-btn');
const messageInput = document.getElementById('message-input');
const chatOutput = document.getElementById('chat-output');

// 渲染聊天消息
function addMessage(text, isUser) {
    const messageDiv = document.createElement('div');
    messageDiv.classList.add(isUser ? 'user-message' : 'bot-message');
    messageDiv.textContent = text;
    chatOutput.appendChild(messageDiv);
    chatOutput.scrollTop = chatOutput.scrollHeight;
}

// 发送消息逻辑
sendBtn.addEventListener('click', async () => {
    const message = messageInput.value.trim();
    if (!message) return;

    addMessage(message, true);
    messageInput.value = '';

    try {
        const response = await fetch('http://你的后端地址/chat', {
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            body: JSON.stringify({ message: message })
        });
        const data = await response.json();
        addMessage(data.response, false);
    } catch (error) {
        addMessage('聊天服务暂时不可用,请稍后重试', false);
        console.error(error);
    }
});

// 回车发送
messageInput.addEventListener('keypress', (e) => {
    if (e.key === 'Enter') sendBtn.click();
});

部署说明

  • 若自有服务器不支持Python,可使用云函数(如阿里云函数计算、腾讯云SCF)或轻量云服务器部署Flask应用,配置好域名即可。
  • 安装依赖:执行pip install flask flask-cors spacy,再运行python -m spacy download en_core_web_sm下载模型。

方案2:纯前端重构(效果接近原版本)

如果必须用纯前端实现,可使用spacy-js替代Python版Spacy,但模型精度会略有下降。

步骤1:引入前端依赖

在HTML的<head>中添加:

<script src="https://unpkg.com/spacy@3.4.0/dist/spacy.min.js"></script>

步骤2:前端重构Chat逻辑

在HTML的<script>标签中添加以下代码:

let nlp;
let corpusSents = [];

// 初始化模型和语料库
async function initChat() {
    nlp = await spacy.load('en_core_web_sm');
    // 加载语料库(需将deutsch_corpus.txt放在前端可访问路径)
    const res = await fetch('deutsch_corpus.txt');
    const text = await res.text();
    const doc = nlp(text);
    corpusSents = Array.from(doc.sents).map(sent => sent.text);
}

// 生成回复
function generateResponse(userInput) {
    const userDoc = nlp(userInput);

    // 处理记忆逻辑(前端用localStorage存储)
    const triggerPhrases = ["i am", "my friend", "my girlfriend", "i was", "i have", "my mother is", "i would be", "i find", "my name is"];
    let remember = false;
    let rememberText = "";
    for (const sent of userDoc.sents) {
        if (triggerPhrases.some(phrase => sent.text.toLowerCase().includes(phrase))) {
            remember = true;
            rememberText = sent.text;
            break;
        }
    }

    if (remember) {
        let memories = JSON.parse(localStorage.getItem('chatMemories') || '[]');
        let replacedText = rememberText.toLowerCase()
            .replace("ich bin", "Du bist")
            .replace("mein", "Dein")
            .replace("meine", "Deine")
            .replace("meine mutter ist", "deine Mutter ist")
            .replace("meine freundin ist", "deine Freundin ist")
            .replace("i would be", "you would be")
            .replace("i find", "you find")
            .replace("my name is", "your name is");
        memories.push(replacedText);
        localStorage.setItem('chatMemories', JSON.stringify(memories));
        return "Ok, I'll remember that!";
    }

    // 计算相似度
    let similarityScores = [];
    for (const sentText of corpusSents) {
        const sentDoc = nlp(sentText);
        const score = userDoc.similarity(sentDoc);
        similarityScores.push({ text: sentText, score });
    }

    similarityScores.sort((a, b) => b.score - a.score);

    if (similarityScores[0].score < 0.5) {
        return "Sorry, I don't understand.";
    }

    return similarityScores[0].text;
}

// 绑定事件
document.addEventListener('DOMContentLoaded', async () => {
    await initChat();

    const sendBtn = document.getElementById('send-btn');
    const messageInput = document.getElementById('message-input');
    const chatOutput = document.getElementById('chat-output');

    function addMessage(text, isUser) {
        const messageDiv = document.createElement('div');
        messageDiv.classList.add(isUser ? 'user-message' : 'bot-message');
        messageDiv.textContent = text;
        chatOutput.appendChild(messageDiv);
        chatOutput.scrollTop = chatOutput.scrollHeight;
    }

    sendBtn.addEventListener('click', () => {
        const message = messageInput.value.trim();
        if (!message) return;

        addMessage(message, true);
        messageInput.value = '';

        const response = generateResponse(message);
        addMessage(response, false);
    });

    messageInput.addEventListener('keypress', (e) => {
        if (e.key === 'Enter') sendBtn.click();
    });
});

注意事项

  • 前端Spacy模型为简化版,相似度计算结果可能与Python原版有差异。
  • 前端无法写入服务器文件,记忆功能改为存储在用户浏览器的localStorage中,仅当前设备有效。

内容的提问来源于stack exchange,提问作者S. Dawid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 17:47:08