M2LOrder项目实战:从零开始搭建一个情感分析Web应用

📅 发布时间:2026/7/6 20:32:36 👁️ 浏览次数:
M2LOrder项目实战:从零开始搭建一个情感分析Web应用
M2LOrder项目实战从零开始搭建一个情感分析Web应用你是不是经常好奇一段文字背后藏着怎样的情绪是喜悦、愤怒还是悲伤今天我们就来动手做一个能“读懂”情绪的小工具。不用怕哪怕你之前没怎么接触过全栈开发跟着这篇教程你也能从零开始一步步搭建起一个属于自己的情感分析Web应用。这个应用会有一个简洁的页面让你输入文字然后点击按钮就能立刻看到分析结果这段文字是积极的、消极的还是中性的。我们还会把每次分析的结果保存下来方便你回头查看历史记录。听起来是不是挺有意思的整个项目我们会用一个叫做M2LOrder的模型作为核心“大脑”负责情感分析的计算。前端页面用大家熟悉的Vue来搭建后端则用轻快的Python框架。我会把每一步都讲清楚从环境准备、代码编写到前后端怎么“对话”最后怎么把它放到服务器上让所有人都能访问。我们的目标很简单让你亲手做出一个能跑起来的、有实用价值的完整应用。1. 项目蓝图与环境准备在开始敲代码之前我们先花几分钟看看我们要建的这个“房子”长什么样以及需要准备哪些“建材”。1.1 项目架构预览我们的应用会采用经典的前后端分离架构。你可以这样理解前端Vue页面就像餐厅的菜单和点餐界面负责展示和收集你的输入一段文字。后端Python服务就像后厨收到“订单”前端发来的文字后调用M2LOrder这个大厨进行“烹饪”情感分析然后把“做好的菜”分析结果送回前厅。数据库则像一个记账本负责把每一单“订单”和“菜品”都记录下来。前端 (Vue 3 Vite Element Plus): 负责用户看到的一切。一个输入框、一个按钮、一个展示结果的区域以及一个历史记录列表。我们选择Vue 3是因为它上手简单生态丰富。Vite能让我们获得极快的开发启动速度Element Plus则提供了很多现成好看的UI组件省去我们自己造轮子的时间。后端 (FastAPI): 负责处理业务逻辑。它提供一个API接口专门接收前端发来的文字然后调用M2LOrder模型进行分析最后把结果返回给前端并存入数据库。FastAPI是一个现代、快速高性能的Python Web框架特别适合构建API而且它的自动交互式文档功能对调试非常友好。AI核心 (M2LOrder): 这是我们项目的灵魂。它是一个预训练好的情感分析模型。我们不需要自己从头训练只需要学会怎么调用它。在本教程中我们会通过一个封装好的Python库来使用它非常简单。数据库 (SQLite): 用来存储每次情感分析的历史记录包括分析的文字、结果、时间戳。SQLite是一个轻量级的数据库不需要单独安装数据库服务一个文件就搞定非常适合我们这个入门级项目。整个数据流的顺序是用户在网页输入文字 - 前端通过HTTP请求将文字发送给后端API - 后端调用M2LOrder模型分析 - 后端将结果保存到数据库 - 后端将结果返回给前端 - 前端将结果展示给用户。1.2 开发环境搭建工欲善其事必先利其器。我们先来把开发环境配置好。首先确保你的电脑上已经安装了Node.js(版本16或以上) 和Python(版本3.8或以上)。你可以在终端或命令提示符里输入node --version和python --version来检查。第一步创建项目文件夹并初始化前端打开你的终端找一个你喜欢的位置执行以下命令# 创建一个项目总目录 mkdir sentiment-analysis-app cd sentiment-analysis-app # 使用Vite快速创建一个Vue 3项目我们给它起名叫web-frontend npm create vuelatest web-frontend在创建过程中命令行会询问你一些选项。为了简化我们这样选择Add TypeScript?-NoAdd JSX Support?-NoAdd Vue Router for Single Page Application?-No(本项目单页足够)Add Pinia for state management?-No(状态简单暂不需要)Add Vitest for Unit Testing?-NoAdd an End-to-End Testing Solution?-NoAdd ESLint for code quality?-Yes(建议保持代码规范)创建完成后进入前端目录并安装UI库和HTTP请求库cd web-frontend npm install npm install element-plus axiosaxios是一个用来向后端发送请求的库。第二步创建并初始化后端服务保持终端打开退回到项目总目录创建后端文件夹cd .. # 退回到 sentiment-analysis-app 目录 mkdir api-backend cd api-backend接下来为Python项目创建虚拟环境并安装依赖。虚拟环境可以隔离项目依赖避免冲突。# 创建虚拟环境Windows用户请使用 python -m venv venv python3 -m venv venv # 激活虚拟环境 # Mac/Linux: source venv/bin/activate # Windows: # venv\Scripts\activate # 安装必要的Python包 pip install fastapi uvicorn sqlalchemy pydantic # 安装我们假设的M2LOrder情感分析库这里我们用transformers库和一个示例模型代替 pip install transformers torch激活虚拟环境后你的命令行提示符前面通常会显示(venv)表示你正在这个独立的环境里工作。环境到这里就准备好了。前端和后端两个“车间”都已经搭建完毕接下来我们就要开始往里面添加机器和生产线了。2. 构建后端“大脑”FastAPI与M2LOrder集成后端是我们的数据处理中心。我们先来构建它重点是创建一个能接收请求、调用模型、并返回结果的API。2.1 创建核心数据模型与数据库在api-backend目录下新建一个名为database.py的文件。这里我们定义数据表和数据库连接。# database.py from sqlalchemy import create_engine, Column, Integer, String, DateTime from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker from datetime import datetime import os # 数据库文件路径 SQLALCHEMY_DATABASE_URL sqlite:///./sentiment.db # 创建数据库引擎 engine create_engine( SQLALCHEMY_DATABASE_URL, connect_args{check_same_thread: False} ) # 创建会话工厂 SessionLocal sessionmaker(autocommitFalse, autoflushFalse, bindengine) # 声明基类 Base declarative_base() # 定义历史记录数据模型 class AnalysisHistory(Base): __tablename__ analysis_history id Column(Integer, primary_keyTrue, indexTrue) text Column(String, nullableFalse) # 用户输入的文本 sentiment Column(String, nullableFalse) # 分析结果positive/negative/neutral confidence Column(String) # 置信度可选用字符串存储如“0.95” created_at Column(DateTime, defaultdatetime.utcnow) # 创建时间 # 创建数据表 Base.metadata.create_all(bindengine) # 依赖项函数用于在请求中获取数据库会话 def get_db(): db SessionLocal() try: yield db finally: db.close()这段代码创建了一个sentiment.db的SQLite数据库文件并定义了一张analysis_history表用来存储每一次的分析记录。2.2 实现M2LOrder情感分析服务接下来我们创建模型加载和预测的逻辑。在api-backend目录下新建model.py。由于“M2LOrder”是一个示例项目名我们这里使用transformers库中一个经典的情感分析模型distilbert-base-uncased-finetuned-sst-2-english来替代演示。# model.py from transformers import pipeline, AutoTokenizer, AutoModelForSequenceClassification import torch # 初始化情感分析管道 # 第一次运行会下载模型需要一点时间 print(正在加载情感分析模型...) sentiment_analyzer pipeline( sentiment-analysis, modeldistilbert-base-uncased-finetuned-sst-2-english, tokenizerdistilbert-base-uncased-finetuned-sst-2-english ) print(模型加载完成) def analyze_sentiment(text: str): 分析文本情感 参数: text: 待分析的文本字符串 返回: dict: 包含情感标签和置信度 if not text or len(text.strip()) 0: return {sentiment: neutral, confidence: 0.0} try: # 调用管道进行分析 result sentiment_analyzer(text[:512])[:1] # 模型可能有输入长度限制这里简单截断 if result: # 结果示例: [{label: POSITIVE, score: 0.9998}] label result[0][label] score result[0][score] # 将标签转换为小写更友好 sentiment_map {POSITIVE: positive, NEGATIVE: negative, NEUTRAL: neutral} sentiment sentiment_map.get(label, neutral) return {sentiment: sentiment, confidence: round(score, 4)} else: return {sentiment: neutral, confidence: 0.0} except Exception as e: print(f情感分析出错: {e}) return {sentiment: error, confidence: 0.0}这个analyze_sentiment函数就是我们的“大厨”。它接收一段文本返回一个包含情感倾向positive/negative/neutral和置信度的字典。2.3 创建FastAPI主应用与接口最后我们把数据库、模型和Web接口串联起来。在api-backend目录下创建main.py文件。# main.py from fastapi import FastAPI, Depends, HTTPException from fastapi.middleware.cors import CORSMiddleware from pydantic import BaseModel from typing import List, Optional from sqlalchemy.orm import Session # 导入我们刚才写的模块 from database import get_db, AnalysisHistory from model import analyze_sentiment from datetime import datetime # 定义请求体和响应体的数据模型 class TextForAnalysis(BaseModel): text: str class SentimentResponse(BaseModel): sentiment: str confidence: float text: str id: Optional[int] None created_at: Optional[datetime] None class HistoryItem(BaseModel): id: int text: str sentiment: str confidence: str created_at: datetime class Config: from_attributes True # 替换 orm_mode # 创建FastAPI应用实例 app FastAPI(title情感分析API, description基于M2LOrder模型的情感分析Web服务) # 添加CORS中间件允许前端跨域访问重要 app.add_middleware( CORSMiddleware, allow_origins[http://localhost:5173], # 前端开发服务器地址 allow_credentialsTrue, allow_methods[*], allow_headers[*], ) # 根路径返回一个简单的欢迎信息 app.get(/) def read_root(): return {message: 情感分析API服务正在运行。请访问 /docs 查看接口文档。} # 情感分析接口 app.post(/analyze/, response_modelSentimentResponse) def analyze_text(request: TextForAnalysis, db: Session Depends(get_db)): 接收文本进行情感分析并保存结果到数据库。 if not request.text: raise HTTPException(status_code400, detail文本内容不能为空) # 1. 调用模型进行分析 analysis_result analyze_sentiment(request.text) # 2. 将结果保存到数据库 db_record AnalysisHistory( textrequest.text, sentimentanalysis_result[sentiment], confidencestr(analysis_result[confidence]) ) db.add(db_record) db.commit() db.refresh(db_record) # 刷新以获取生成的id等字段 # 3. 构造返回给前端的响应 return { id: db_record.id, text: request.text, sentiment: analysis_result[sentiment], confidence: analysis_result[confidence], created_at: db_record.created_at } # 获取历史记录接口 app.get(/history/, response_modelList[HistoryItem]) def get_history(skip: int 0, limit: int 20, db: Session Depends(get_db)): 获取情感分析历史记录按时间倒序排列。 history db.query(AnalysisHistory).order_by(AnalysisHistory.created_at.desc()).offset(skip).limit(limit).all() return history这个文件创建了三个核心接口GET /一个简单的健康检查接口。POST /analyze/核心接口接收文本分析情感存入数据库并返回结果。GET /history/获取历史分析记录的接口。注意我们通过CORSMiddleware允许来自http://localhost:5173Vite默认的前端地址的跨域请求这是前后端能成功通信的关键。现在让我们启动后端服务看看。在api-backend目录下确保虚拟环境已激活运行uvicorn main:app --reload --host 0.0.0.0 --port 8000打开浏览器访问http://localhost:8000/docs你应该能看到FastAPI自动生成的交互式API文档。可以在这里尝试调用/analyze/接口测试一下后端是否工作正常。3. 打造前端“门面”Vue 3交互界面后端引擎已经启动现在我们来构建用户直接交互的界面。前端的目标是做一个简洁美观的页面让用户输入文字、查看分析结果和历史记录。3.1 项目结构与组件初始化我们使用Vue的单文件组件.vue来组织代码。首先清理一下web-frontend/src/目录下默认生成的一些文件我们不需要它们删除src/components/下的所有.vue文件。删除src/assets/下的base.css保留logo.svg即可。修改src/App.vue文件。我们先来配置Element Plus让它能在整个应用中使用。修改src/main.js文件// src/main.js import { createApp } from vue import App from ./App.vue // 引入Element Plus及其样式 import ElementPlus from element-plus import element-plus/dist/index.css const app createApp(App) app.use(ElementPlus) app.mount(#app)3.2 构建主应用组件现在重写src/App.vue文件这里将包含我们应用的所有核心逻辑和界面。!-- src/App.vue -- template div idapp el-container classmain-container el-header classapp-header h1el-iconPromotion //el-icon 情感分析实验室/h1 p classsubtitle输入一段文字让AI解读其中的情绪色彩/p /el-header el-main classapp-main !-- 输入与分析区域 -- el-card classanalysis-card shadowhover template #header div classcard-header spanel-iconEdit //el-icon 输入与分析/span /div /template el-input v-modelinputText :autosize{ minRows: 4, maxRows: 8 } typetextarea placeholder请输入你想要分析情感的文本例如今天天气真好心情特别愉快 或 这个任务太难了让我感到非常沮丧。 clearable classtext-input / div classaction-bar el-button typeprimary :iconPromotion clickanalyzeSentiment :loadingisAnalyzing :disabled!inputText.trim() {{ isAnalyzing ? 分析中... : 开始分析 }} /el-button el-button :iconDelete clickinputText 清空/el-button /div !-- 分析结果展示 -- div v-ifcurrentResult classresult-section el-dividerel-iconComment //el-icon 分析结果/el-divider div classresult-content el-tag :typegetSentimentTagType(currentResult.sentiment) sizelarge classsentiment-tag el-icon v-ifcurrentResult.sentiment positiveSunny //el-icon el-icon v-ifcurrentResult.sentiment negativeCloudy //el-icon el-icon v-ifcurrentResult.sentiment neutralPartlyCloudy //el-icon {{ getSentimentText(currentResult.sentiment) }} /el-tag div classconfidence 置信度: strong{{ (currentResult.confidence * 100).toFixed(2) }}%/strong /div p classoriginal-textstrong原文/strong{{ currentResult.text }}/p p classtimesmall分析于 {{ formatTime(currentResult.created_at) }}/small/p /div /div /el-card !-- 历史记录区域 -- el-card classhistory-card shadowhover template #header div classcard-header spanel-iconClock //el-icon 分析历史/span el-button :iconRefresh sizesmall clickfetchHistory刷新/el-button /div /template el-table :datahistoryList stripe stylewidth: 100% v-loadingisLoadingHistory el-table-column propid labelID width80 / el-table-column proptext label文本 min-width200 show-overflow-tooltip / el-table-column propsentiment label情感 width120 template #defaultscope el-tag :typegetSentimentTagType(scope.row.sentiment) sizesmall {{ getSentimentText(scope.row.sentiment) }} /el-tag /template /el-table-column el-table-column propconfidence label置信度 width120 template #defaultscope {{ (parseFloat(scope.row.confidence) * 100).toFixed(1) }}% /template /el-table-column el-table-column propcreated_at label时间 width180 template #defaultscope {{ formatTime(scope.row.created_at) }} /template /el-table-column /el-table div classhistory-hint v-ifhistoryList.length 0 暂无历史记录快去分析一段文本吧 /div /el-card /el-main el-footer classapp-footer pPowered by M2LOrder Vue 3 | 一个简单的全栈项目实践/p /el-footer /el-container /div /template script setup import { ref, onMounted } from vue import axios from axios import { Promotion, Edit, Delete, Comment, Sunny, Cloudy, PartlyCloudy, Clock, Refresh } from element-plus/icons-vue // 后端API基础地址根据你的后端运行地址调整 const API_BASE_URL http://localhost:8000 // 响应式数据 const inputText ref() const currentResult ref(null) const historyList ref([]) const isAnalyzing ref(false) const isLoadingHistory ref(false) // 情感标签类型和文本映射 const getSentimentTagType (sentiment) { const map { positive: success, negative: danger, neutral: info, error: warning } return map[sentiment] || info } const getSentimentText (sentiment) { const map { positive: 积极, negative: 消极, neutral: 中性, error: 出错 } return map[sentiment] || 未知 } // 格式化时间 const formatTime (timeStr) { if (!timeStr) return const date new Date(timeStr) return date.toLocaleString(zh-CN) } // 调用后端API进行情感分析 const analyzeSentiment async () { if (!inputText.value.trim()) { ElMessage.warning(请输入要分析的文本) return } isAnalyzing.value true try { const response await axios.post(${API_BASE_URL}/analyze/, { text: inputText.value }) currentResult.value response.data ElMessage.success(分析完成) // 分析完成后刷新历史记录列表 fetchHistory() // 可选清空输入框 // inputText.value } catch (error) { console.error(分析请求失败:, error) ElMessage.error(分析失败请检查网络或后端服务) currentResult.value { sentiment: error, confidence: 0, text: inputText.value } } finally { isAnalyzing.value false } } // 获取历史记录 const fetchHistory async () { isLoadingHistory.value true try { const response await axios.get(${API_BASE_URL}/history/) historyList.value response.data } catch (error) { console.error(获取历史记录失败:, error) ElMessage.error(获取历史记录失败) } finally { isLoadingHistory.value false } } // 页面加载时获取历史记录 onMounted(() { fetchHistory() }) /script style scoped #app { font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif; min-height: 100vh; background-color: #f5f7fa; } .main-container { max-width: 1200px; margin: 0 auto; min-height: 100vh; } .app-header { text-align: center; padding-top: 30px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; } .app-header h1 { margin-bottom: 10px; font-size: 2.5rem; } .subtitle { opacity: 0.9; font-size: 1.1rem; } .app-main { padding: 20px; } .analysis-card, .history-card { margin-bottom: 24px; border-radius: 12px; } .card-header { display: flex; justify-content: space-between; align-items: center; font-size: 1.2rem; font-weight: bold; } .text-input { margin-bottom: 20px; } .action-bar { display: flex; gap: 12px; margin-bottom: 20px; } .result-section { margin-top: 20px; } .sentiment-tag { font-size: 1.1rem; padding: 10px 20px; margin-bottom: 15px; } .confidence { margin: 10px 0; font-size: 1rem; } .original-text { background-color: #f9f9f9; padding: 12px; border-radius: 6px; border-left: 4px solid #409eff; } .time { color: #909399; text-align: right; margin-top: 10px; } .history-hint { text-align: center; padding: 40px; color: #c0c4cc; font-size: 1rem; } .app-footer { text-align: center; padding: 20px; color: #909399; font-size: 0.9rem; border-top: 1px solid #e4e7ed; } /style这个组件做了以下几件事数据绑定使用Vue的ref创建了响应式数据如输入文本inputText、当前结果currentResult和历史列表historyList。用户交互文本输入框绑定到inputText。“开始分析”按钮点击时触发analyzeSentiment函数。“清空”按钮用于重置输入框。“刷新”按钮用于手动刷新历史记录。网络请求使用axios库向后端定义的接口/analyze/和/history/发送HTTP请求。结果展示根据分析结果的情感倾向positive/negative/neutral动态显示不同颜色和图标的表情标签并展示置信度和原文。历史记录以表格形式展示以往的分析记录包括ID、文本、情感标签、置信度和时间。样式美化使用Element Plus的组件和自定义CSS使界面看起来更美观。3.3 启动前端并测试联调现在让我们启动前端开发服务器。在web-frontend目录下运行npm run devVite会启动一个开发服务器通常地址是http://localhost:5173。用浏览器打开这个地址。关键一步确保后端服务也在运行uvicorn main:app --reload --host 0.0.0.0 --port 8000。现在在前端页面输入一段文字比如“我中大奖了太开心了”点击“开始分析”。如果一切顺利几秒钟后你就能看到分析结果大概率是“积极”并且下方的历史记录表格里会新增一条记录。如果遇到问题请按以下步骤排查检查控制台打开浏览器的开发者工具F12查看“网络(Network)”和“控制台(Console)”标签页看是否有红色的错误信息。常见的错误是跨域CORS问题请确认后端main.py中allow_origins包含了前端地址http://localhost:5173。检查后端日志查看运行后端服务的终端窗口看是否有请求进来或者模型加载、数据库操作是否有报错。直接测试API在浏览器访问http://localhost:8000/docs尝试直接用Swagger UI调用/analyze/接口看后端本身是否工作正常。当你在前端页面成功看到分析结果和历史记录时恭喜你一个完整的前后端分离的情感分析应用已经在你本地跑起来了4. 项目部署与上线指南让应用在本地运行只是第一步最终我们需要把它部署到服务器上让其他人也能通过互联网访问。这里我们介绍两种常见的、相对简单的部署方式。4.1 部署准备生产环境优化在部署前我们需要对代码做一些小的调整让它更适合生产环境。后端调整 (api-backend/main.py) 修改CORS设置允许生产环境的前端域名访问或者根据情况调整。# 在生产环境中你需要将 allow_origins 替换为你前端实际部署的域名例如 [https://yourdomain.com] # 对于测试可以暂时允许所有来源不推荐用于生产 app.add_middleware( CORSMiddleware, allow_origins[*], # 生产环境请替换为具体域名 # ... 其他配置保持不变 )同时可以考虑移除--reload参数并可能使用像Gunicorn这样的ASGI服务器来替代直接运行uvicorn以获得更好的性能。前端调整 (web-frontend/vite.config.js) 我们需要在构建前端时明确知道后端API的地址。创建或修改web-frontend/vite.config.js// vite.config.js import { defineConfig } from vite import vue from vitejs/plugin-vue // https://vitejs.dev/config/ export default defineConfig({ plugins: [vue()], // 配置生产环境的后端API地址 server: { proxy: { // 开发环境代理解决跨域 /api: { target: http://localhost:8000, changeOrigin: true, rewrite: (path) path.replace(/^\/api/, ) } } }, // 构建配置 build: { outDir: dist, // 构建输出目录 // 你可以在这里配置公共路径如果你部署在子路径下 // base: /your-subpath/, } })同时修改前端代码中API_BASE_URL的定义使其更灵活// src/App.vue (script部分顶部) // 根据环境变量或构建模式决定API地址 const API_BASE_URL import.meta.env.PROD ? /api : http://localhost:8000 // 注意生产环境需要你的Web服务器如Nginx将 /api 的请求代理到后端服务4.2 部署方案一传统云服务器这是最通用、控制力最强的方案。你需要一台云服务器如阿里云ECS、腾讯云CVM。服务器准备购买一台Linux服务器如Ubuntu 22.04通过SSH登录。环境安装在服务器上安装Node.js、Python、pip、NginxWeb服务器、Supervisor进程管理等。上传代码使用Git克隆你的项目代码到服务器或者通过FTP/SFTP上传。构建前端在服务器上进入web-frontend目录运行npm run build。这会生成一个dist文件夹里面是静态文件。配置Nginx将dist文件夹内的内容放到Nginx的网站根目录如/var/www/sentiment-app。配置Nginx让它将前端请求指向dist目录同时将/api/路径的请求代理到运行在localhost:8000的后端服务。一个简化的Nginx配置示例 (/etc/nginx/sites-available/sentiment-app)server { listen 80; server_name your-domain.com; # 你的域名或服务器IP # 前端静态文件 location / { root /var/www/sentiment-app; try_files $uri $uri/ /index.html; } # 代理后端API请求 location /api/ { proxy_pass http://127.0.0.1:8000/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }启动后端服务使用Supervisor来管理后端进程确保它一直在运行并在崩溃时自动重启。创建一个Supervisor配置文件来运行uvicorn或gunicorn命令。重启服务重启Nginx和Supervisor你的应用就应该可以通过服务器的IP地址或域名访问了。4.3 部署方案二容器化部署Docker容器化部署更现代能保证环境一致性也更容易迁移。你需要服务器上安装Docker和Docker Compose。编写Dockerfile为前端和后端分别创建Dockerfile定义如何构建镜像。后端Dockerfile(api-backend/Dockerfile)FROM python:3.10-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . CMD [uvicorn, main:app, --host, 0.0.0.0, --port, 8000]前端Dockerfile(web-frontend/Dockerfile)FROM node:18-alpine as build WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build FROM nginx:alpine COPY --frombuild /app/dist /usr/share/nginx/html COPY nginx.conf /etc/nginx/conf.d/default.conf EXPOSE 80还需要一个nginx.conf文件来配置代理类似方案一中的Nginx配置。编写docker-compose.yml在项目根目录创建这个文件定义前端、后端两个服务。version: 3.8 services: backend: build: ./api-backend ports: - 8000:8000 environment: - DATABASE_URLsqlite:///./sentiment.db # 可以将数据库文件挂载到宿主机防止数据丢失 volumes: - ./data:/app/data frontend: build: ./web-frontend ports: - 80:80 depends_on: - backend构建与运行在服务器上进入项目根目录运行docker-compose up -d。Docker会自动构建镜像并启动两个容器。访问应用现在你可以通过服务器的IP地址HTTP端口80直接访问应用了。后端服务被前端Nginx容器内部代理。方案二将所有依赖和环境打包在容器里部署和更新docker-compose pull docker-compose up -d都非常方便。5. 总结与后续探索跟着教程走下来我们从零开始完成了一个具备完整功能的情感分析Web应用。这个过程涵盖了现代Web开发的核心流程设计架构、搭建环境、编写后端API、构建前端界面、前后端联调最后还探讨了如何部署上线。这个项目虽然不大但麻雀虽小五脏俱全。你亲手实践了如何将一个AI模型M2LOrder/替代模型封装成服务并通过RESTful API提供给前端调用也体验了Vue 3的响应式开发以及如何使用Element Plus快速搭建界面。更重要的是你打通了从数据输入、AI处理、结果展示到数据持久化的完整链路。实际用下来这个基础版本跑通没问题但肯定还有不少可以打磨的地方。比如现在的模型对中文的支持可能没那么好因为我们用的示例模型是英文的你可以去寻找或微调一个更擅长中文情感分析的模型来替换。前端界面也可以做得更丰富比如增加情感趋势图表、支持批量文本分析、或者加入用户登录功能来区分不同人的历史记录。部署环节我们介绍了两种主流方式。传统服务器部署让你对底层有更多控制而Docker方案则更简洁、更易于维护和扩展。你可以根据自己的熟悉程度和项目需求来选择。技术学习最好的方式就是动手去做。这个项目就是一个很好的起点。希望它不仅能帮你理解全栈开发的基本逻辑更能激发你去探索更多可能性——换一个更强大的模型增加更复杂的功能或者用不同的技术栈重新实现一遍。编程的乐趣正是在于这种从无到有、不断优化的创造过程。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。