毕业设计开发计划
·3489 words·17 mins
Table of Contents
毕业设计开发计划 #
题目:社交媒体评论生成与评估系统设计与实现
学生:[你的姓名]
时间范围:2026年2月24日 - 2026年5月底
技术栈:FastAPI + React + OpenAI API + SQLite + Ant Design
项目概览 #
核心功能模块 #
├── 后端 (FastAPI)
│ ├── 数据管理模块
│ ├── 评论生成模块(核心创新点1)
│ ├── 多智能体评估模块(核心创新点2)
│ └── API接口层
│
├── 前端 (React)
│ ├── 帖子管理界面
│ ├── 评论生成界面
│ ├── 评估结果可视化
│ └── 数据分析看板
│
└── 数据层 (SQLite)
├── 帖子表
├── 评论表
├── 评估结果表
└── Agent配置表
MVP vs 完整版功能对比 #
| 功能 | MVP版本(3月15日前) | 完整版本(4月15日前) |
|---|---|---|
| 帖子管理 | 手动输入单个帖子 | 批量导入、分类管理 |
| 评论生成 | 3种风格、单次生成 | 5种风格、批量生成、参数可调 |
| Agent评估 | 3个固定Agent | 5-8个可配置Agent,多维度评分 |
| 前端展示 | 基础列表展示 | 雷达图、柱状图、对比分析 |
| 数据导出 | 无 | 导出评估报告(Excel/PDF) |
第一阶段:基础框架搭建(2月24日-3月3日,7天) #
Week 1: 2月24日-3月3日 #
Day 1-2: 环境搭建与项目初始化 #
后端任务:
# 创建项目目录
mkdir social-comment-system
cd social-comment-system
# 后端初始化
mkdir backend
cd backend
poetry init
poetry add fastapi uvicorn sqlalchemy openai python-dotenv pydantic
poetry add --dev pytest black flake8
# 创建基础目录结构
mkdir -p app/{api,core,models,services,schemas,utils}
touch app/__init__.py
touch app/main.py
目录结构:
backend/
├── app/
│ ├── __init__.py
│ ├── main.py # FastAPI应用入口
│ ├── config.py # 配置文件
│ ├── database.py # 数据库连接
│ │
│ ├── api/ # API路由
│ │ ├── __init__.py
│ │ ├── posts.py # 帖子相关API
│ │ ├── comments.py # 评论相关API
│ │ └── evaluations.py # 评估相关API
│ │
│ ├── models/ # SQLAlchemy模型
│ │ ├── __init__.py
│ │ ├── post.py
│ │ ├── comment.py
│ │ └── evaluation.py
│ │
│ ├── schemas/ # Pydantic模式
│ │ ├── __init__.py
│ │ ├── post.py
│ │ ├── comment.py
│ │ └── evaluation.py
│ │
│ ├── services/ # 业务逻辑
│ │ ├── __init__.py
│ │ ├── comment_generator.py # 评论生成服务(核心)
│ │ ├── agent_evaluator.py # 多Agent评估服务(核心)
│ │ └── prompt_templates.py # Prompt模板管理
│ │
│ └── utils/ # 工具函数
│ ├── __init__.py
│ └── llm_client.py # LLM调用封装
│
├── tests/ # 测试文件
├── .env # 环境变量
├── pyproject.toml
└── README.md
前端任务:
# 前端初始化
cd ..
npx create-react-app frontend --template typescript
cd frontend
npm install antd axios recharts react-router-dom
npm install --save-dev @types/react-router-dom
检查点:
- 后端能启动并访问 http://localhost:8000/docs
- 前端能启动并访问 http://localhost:3000
- 数据库能连接(SQLite文件创建成功)
Day 3-4: 数据库模型设计与实现 #
数据库表设计:
# models/post.py
from sqlalchemy import Column, Integer, String, Text, DateTime, Enum
from datetime import datetime
import enum
class PostCategory(str, enum.Enum):
CURRENT_AFFAIRS = "时事热点"
TECHNOLOGY = "科技产品"
ENTERTAINMENT = "娱乐八卦"
LIFESTYLE = "生活分享"
CONTROVERSIAL = "争议话题"
class Post(Base):
__tablename__ = "posts"
id = Column(Integer, primary_key=True, index=True)
title = Column(String(255), nullable=False)
content = Column(Text, nullable=False)
category = Column(Enum(PostCategory), nullable=False)
author = Column(String(100))
created_at = Column(DateTime, default=datetime.utcnow)
# 关系
comments = relationship("Comment", back_populates="post")
# models/comment.py
class CommentStyle(str, enum.Enum):
HUMOROUS = "幽默型"
RATIONAL = "理性型"
EMOTIONAL = "情感型"
CONTROVERSIAL = "争议型"
SUPPORTIVE = "支持型"
class Comment(Base):
__tablename__ = "comments"
id = Column(Integer, primary_key=True, index=True)
post_id = Column(Integer, ForeignKey("posts.id"))
content = Column(Text, nullable=False)
style = Column(Enum(CommentStyle), nullable=False)
generation_params = Column(JSON) # 存储生成参数
created_at = Column(DateTime, default=datetime.utcnow)
# 关系
post = relationship("Post", back_populates="comments")
evaluations = relationship("Evaluation", back_populates="comment")
# models/evaluation.py
class AgentPersona(str, enum.Enum):
EXPERT = "资深爱好者"
CASUAL = "路人用户"
CRITIC = "批判者"
EMPATHY = "情感共鸣者"
RATIONAL = "理性分析者"
class Evaluation(Base):
__tablename__ = "evaluations"
id = Column(Integer, primary_key=True, index=True)
comment_id = Column(Integer, ForeignKey("comments.id"))
agent_persona = Column(Enum(AgentPersona), nullable=False)
# 评分维度(1-5分)
relevance_score = Column(Integer) # 内容相关性
emotional_score = Column(Integer) # 情感共鸣
discussion_score = Column(Integer) # 讨论价值
quality_score = Column(Integer) # 表达质量
overall_score = Column(Float) # 综合评分
# 行为
action = Column(String(20)) # like/dislike/neutral
feedback = Column(Text) # Agent的评语
created_at = Column(DateTime, default=datetime.utcnow)
# 关系
comment = relationship("Comment", back_populates="evaluations")
检查点:
- 数据库迁移成功,表创建完成
- 能插入测试数据
- CRUD操作测试通过
Day 5-7: 基础API开发 #
实现基础CRUD接口:
# api/posts.py
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from typing import List
router = APIRouter(prefix="/api/posts", tags=["posts"])
@router.post("/", response_model=schemas.Post)
def create_post(post: schemas.PostCreate, db: Session = Depends(get_db)):
"""创建新帖子"""
db_post = models.Post(**post.dict())
db.add(db_post)
db.commit()
db.refresh(db_post)
return db_post
@router.get("/", response_model=List[schemas.Post])
def list_posts(skip: int = 0, limit: int = 10, db: Session = Depends(get_db)):
"""获取帖子列表"""
posts = db.query(models.Post).offset(skip).limit(limit).all()
return posts
@router.get("/{post_id}", response_model=schemas.PostDetail)
def get_post(post_id: int, db: Session = Depends(get_db)):
"""获取帖子详情(包含评论)"""
post = db.query(models.Post).filter(models.Post.id == post_id).first()
if not post:
raise HTTPException(status_code=404, detail="Post not found")
return post
前端基础页面:
// src/pages/PostList.tsx
import { List, Card, Button, Tag } from 'antd';
import { useEffect, useState } from 'react';
import axios from 'axios';
const PostList = () => {
const [posts, setPosts] = useState([]);
useEffect(() => {
axios.get('http://localhost:8000/api/posts')
.then(res => setPosts(res.data));
}, []);
return (
<List
dataSource={posts}
renderItem={post => (
<Card title={post.title}>
<Tag>{post.category}</Tag>
<p>{post.content}</p>
<Button>生成评论</Button>
</Card>
)}
/>
);
};
检查点:
- Swagger文档正常显示所有API
- 前端能调用后端API获取数据
- 能创建、查询帖子
第二阶段:核心功能开发(3月4日-3月15日,12天) #
Week 2: 3月4日-3月10日 - 评论生成模块 #
Day 8-9: LLM客户端封装与Prompt模板设计 #
LLM客户端:
# utils/llm_client.py
from openai import OpenAI
from typing import Optional, Dict, Any
import os
class LLMClient:
"""封装LLM调用,支持任何兼容OpenAI接口的模型"""
def __init__(self):
self.client = OpenAI(
api_key=os.getenv("OPENAI_API_KEY"),
base_url=os.getenv("OPENAI_BASE_URL") # 可换成其他API
)
self.model = os.getenv("MODEL_NAME", "gpt-3.5-turbo")
def chat_completion(
self,
messages: list,
temperature: float = 0.7,
max_tokens: int = 500,
**kwargs
) -> str:
"""调用Chat接口"""
try:
response = self.client.chat.completions.create(
model=self.model,
messages=messages,
temperature=temperature,
max_tokens=max_tokens,
**kwargs
)
return response.choices[0].message.content
except Exception as e:
print(f"LLM调用失败: {e}")
raise
def batch_generate(
self,
prompts: list,
temperature: float = 0.7
) -> list:
"""批量生成"""
results = []
for prompt in prompts:
result = self.chat_completion(
messages=[{"role": "user", "content": prompt}],
temperature=temperature
)
results.append(result)
return results
Prompt模板库(核心创新):
# services/prompt_templates.py
class PromptTemplates:
"""评论生成的Prompt模板库"""
# 基础分析模板
POST_ANALYSIS_TEMPLATE = """
请分析以下社交媒体帖子的关键信息:
【帖子标题】{title}
【帖子内容】{content}
【帖子分类】{category}
请提取:
1. 核心主题(用3-5个关键词概括)
2. 情感倾向(正面/负面/中性/复杂)
3. 讨论焦点(用户可能关注的点)
4. 潜在争议点(如果有)
以JSON格式输出。
"""
# 不同风格的评论生成模板
STYLE_TEMPLATES = {
"幽默型": """
你是一个幽默风趣的社交媒体用户,擅长用轻松诙谐的方式评论。
【帖子内容】{content}
【核心主题】{topic}
【情感倾向】{sentiment}
请生成一条幽默型评论,要求:
1. 100字以内
2. 使用网络流行语或梗(适度)
3. 保持友善,不讽刺挖苦
4. 与帖子内容相关
只输出评论内容,不要其他说明。
""",
"理性型": """
你是一个理性客观的社交媒体用户,擅长分析和思考。
【帖子内容】{content}
【核心主题】{topic}
【讨论焦点】{focus}
请生成一条理性分析型评论,要求:
1. 150字左右
2. 逻辑清晰,有理有据
3. 可以提出不同观点,但要尊重原帖
4. 适当提出问题引发思考
只输出评论内容,不要其他说明。
""",
"情感共鸣型": """
你是一个情感丰富、善于共鸣的社交媒体用户。
【帖子内容】{content}
【情感倾向】{sentiment}
【核心主题】{topic}
请生成一条情感共鸣型评论,要求:
1. 80-120字
2. 表达真挚的情感(开心/感动/理解/支持)
3. 可以分享类似经历
4. 语气温暖、真诚
只输出评论内容,不要其他说明。
""",
"争议型": """
你是一个喜欢提出不同观点、引发讨论的用户(理性辩论,不是杠精)。
【帖子内容】{content}
【核心主题】{topic}
【可能的争议点】{controversial_points}
请生成一条提出不同观点的评论,要求:
1. 100-150字
2. 礼貌地提出不同看法
3. 有理有据,不是无端质疑
4. 能引发进一步讨论
只输出评论内容,不要其他说明。
""",
"支持型": """
你是一个积极正面、乐于鼓励他人的社交媒体用户。
【帖子内容】{content}
【核心主题】{topic}
请生成一条支持鼓励型评论,要求:
1. 50-100字
2. 表达认同和支持
3. 可以提供建议或加油打气
4. 真诚不空洞
只输出评论内容,不要其他说明。
"""
}
# Few-shot示例(提升生成质量)
FEW_SHOT_EXAMPLES = {
"幽默型": [
{
"post": "今天加班到凌晨,累死了",
"comment": "兄弟,这不是加班,这是在公司过夜啊😂 记得明天带个睡袋,省得回家了"
},
{
"post": "新买的iPhone又摔碎屏了",
"comment": "这就是传说中的"贵族运动"——摔iPhone🤣 不过认真说,建议贴个钢化膜,亲测有效!"
}
],
"理性型": [
{
"post": "觉得现在年轻人都不爱读书了",
"comment": "这个观点可能需要更多数据支持。根据《2023年国民阅读报告》,年轻人的阅读量其实在增加,只是阅读方式从纸质书转向了电子书和有声书。我们要区分"阅读载体变化"和"阅读兴趣下降"这两个概念。"
}
]
}
@classmethod
def build_comment_prompt(
cls,
post_content: str,
post_analysis: dict,
style: str,
use_few_shot: bool = True
) -> str:
"""构建评论生成Prompt"""
template = cls.STYLE_TEMPLATES.get(style, cls.STYLE_TEMPLATES["理性型"])
# 填充模板
prompt = template.format(
content=post_content,
topic=post_analysis.get("topic", ""),
sentiment=post_analysis.get("sentiment", ""),
focus=post_analysis.get("focus", ""),
controversial_points=post_analysis.get("controversial_points", "")
)
# 添加Few-shot示例
if use_few_shot and style in cls.FEW_SHOT_EXAMPLES:
examples = cls.FEW_SHOT_EXAMPLES[style]
few_shot_text = "\n\n【参考示例】\n"
for ex in examples:
few_shot_text += f"帖子:{ex['post']}\n评论:{ex['comment']}\n\n"
prompt = few_shot_text + prompt
return prompt
检查点:
- LLM客户端能正常调用
- 5种风格的Prompt模板设计完成
- 能生成基础评论(质量暂不考虑)
Day 10-12: 评论生成服务实现 #
# services/comment_generator.py
import json
from typing import List, Dict, Optional
from .prompt_templates import PromptTemplates
from ..utils.llm_client import LLMClient
class CommentGenerator:
"""评论生成服务(核心模块)"""
def __init__(self):
self.llm_client = LLMClient()
self.templates = PromptTemplates()
def analyze_post(self, post_content: str, post_title: str, category: str) -> dict:
"""第一步:分析帖子内容"""
prompt = self.templates.POST_ANALYSIS_TEMPLATE.format(
title=post_title,
content=post_content,
category=category
)
response = self.llm_client.chat_completion(
messages=[
{"role": "system", "content": "你是一个专业的文本分析助手。"},
{"role": "user", "content": prompt}
],
temperature=0.3 # 分析阶段用低温度
)
try:
analysis = json.loads(response)
except:
# 如果返回不是JSON,手动解析
analysis = {"topic": "未知", "sentiment": "中性"}
return analysis
def generate_comment(
self,
post_content: str,
post_title: str,
category: str,
style: str,
temperature: float = 0.7,
use_few_shot: bool = True
) -> Dict[str, any]:
"""生成单条评论"""
# 1. 分析帖子
analysis = self.analyze_post(post_content, post_title, category)
# 2. 构建生成Prompt
prompt = self.templates.build_comment_prompt(
post_content=post_content,
post_analysis=analysis,
style=style,
use_few_shot=use_few_shot
)
# 3. 调用LLM生成
comment_text = self.llm_client.chat_completion(
messages=[
{"role": "system", "content": f"你是一个{style}的社交媒体用户。"},
{"role": "user", "content": prompt}
],
temperature=temperature
)
return {
"content": comment_text.strip(),
"style": style,
"analysis": analysis,
"params": {
"temperature": temperature,
"use_few_shot": use_few_shot
}
}
def generate_multiple_comments(
self,
post_id: int,
post_content: str,
post_title: str,
category: str,
styles: Optional[List[str]] = None,
count_per_style: int = 1
) -> List[Dict]:
"""批量生成多条评论"""
if styles is None:
styles = ["幽默型", "理性型", "情感共鸣型"]
comments = []
for style in styles:
for _ in range(count_per_style):
comment_data = self.generate_comment(
post_content=post_content,
post_title=post_title,
category=category,
style=style
)
comments.append(comment_data)
return comments
API接口:
# api/comments.py
@router.post("/generate", response_model=schemas.CommentGenerateResponse)
def generate_comments(
request: schemas.CommentGenerateRequest,
db: Session = Depends(get_db)
):
"""为帖子生成评论"""
# 获取帖子
post = db.query(models.Post).filter(models.Post.id == request.post_id).first()
if not post:
raise HTTPException(status_code=404, detail="Post not found")
# 生成评论
generator = CommentGenerator()
comments_data = generator.generate_multiple_comments(
post_id=post.id,
post_content=post.content,
post_title=post.title,
category=post.category,
styles=request.styles,
count_per_style=request.count_per_style
)
# 保存到数据库
db_comments = []
for comment_data in comments_data:
db_comment = models.Comment(
post_id=post.id,
content=comment_data["content"],
style=comment_data["style"],
generation_params=comment_data["params"]
)
db.add(db_comment)
db_comments.append(db_comment)
db.commit()
return {
"post_id": post.id,
"comments": db_comments,
"count": len(db_comments)
}
检查点:
- 能成功生成5种风格的评论
- 生成的评论质量可接受(人工检查)
- API能正常返回结果
- 前端能调用并显示生成的评论
Week 3: 3月11日-3月15日 - 多智能体评估模块(最大创新点) #
Day 13-14: Agent人设设计与Prompt工程 #
Agent人设配置:
# services/agent_personas.py
class AgentPersonas:
"""虚拟用户Agent人设配置"""
PERSONAS = {
"资深爱好者": {
"name": "资深爱好者",
"description": "对该领域有深入了解,标准较高,关注细节和专业性",
"age": 28,
"occupation": "行业从业者",
"personality_traits": ["严谨", "挑剔", "专业"],
"evaluation_focus": ["内容专业性", "逻辑严密性", "信息准确性"],
"system_prompt": """
你是一位资深的领域爱好者,对内容质量要求很高。
评价评论时,你会关注:
1. 内容是否准确、专业
2. 逻辑是否严密
3. 是否有深度见解
你不太容易被表面的幽默或煽情打动,更看重实质内容。
"""
},
"路人用户": {
"name": "路人用户",
"description": "普通网友,没有特别偏好,看重通俗易懂和实用性",
"age": 25,
"occupation": "普通上班族",
"personality_traits": ["随和", "实用主义", "容易满足"],
"evaluation_focus": ["可读性", "实用性", "是否有趣"],
"system_prompt": """
你是一位普通的社交媒体用户,没有特别的专业背景。
评价评论时,你会关注:
1. 是否容易理解
2. 是否有用或有趣
3. 表达是否自然
你比较随和,只要评论不无聊或不恶意,都能接受。
"""
},
"批判者": {
"name": "批判者",
"description": "喜欢挑毛病,但不是无脑杠,会指出真实问题",
"age": 32,
"occupation": "评论员/自媒体",
"personality_traits": ["批判性思维", "追求完美", "直言不讳"],
"evaluation_focus": ["逻辑漏洞", "偏见", "表述问题"],
"system_prompt": """
你是一位具有批判性思维的用户,善于发现问题。
评价评论时,你会:
1. 指出逻辑不严谨的地方
2. 质疑没有依据的观点
3. 挑出表达不当的问题
但你不是杠精,批评是为了让内容更好,不是为了抬杠。
"""
},
"情感共鸣者": {
"name": "情感共鸣者",
"description": "情感丰富,容易被真情实感打动",
"age": 23,
"occupation": "学生/文艺工作者",
"personality_traits": ["感性", "善良", "富有同理心"],
"evaluation_focus": ["情感真挚度", "共鸣感", "温度"],
"system_prompt": """
你是一位情感丰富的用户,容易被真挚的情感打动。
评价评论时,你会关注:
1. 是否有真情实感
2. 是否能引起共鸣
3. 语气是否温暖、善意
你不太在意专业性,更看重人与人之间的情感连接。
"""
},
"理性分析者": {
"name": "理性分析者",
"description": "注重数据和逻辑,喜欢客观分析",
"age": 30,
"occupation": "研究员/工程师",
"personality_traits": ["理性", "客观", "数据导向"],
"evaluation_focus": ["论据充分性", "逻辑性", "客观性"],
"system_prompt": """
你是一位理性的用户,习惯用数据和逻辑看待问题。
评价评论时,你会关注:
1. 是否有数据或事实支撑
2. 论证逻辑是否清晰
3. 是否避免了情绪化表达
你认为好的评论应该客观、理性、有理有据。
"""
},
"幽默爱好者": {
"name": "幽默爱好者",
"description": "喜欢轻松有趣的内容,看重娱乐性",
"age": 21,
"occupation": "学生",
"personality_traits": ["乐观", "轻松", "追求有趣"],
"evaluation_focus": ["趣味性", "创意", "轻松氛围"],
"system_prompt": """
你是一位喜欢幽默内容的用户,上网就是为了开心。
评价评论时,你会关注:
1. 是否有趣、好笑
2. 是否有创意
3. 是否能让人轻松
你不喜欢太严肃、太长的评论,更喜欢简短有趣的内容。
"""
},
"中立观察者": {
"name": "中立观察者",
"description": "保持中立,平衡看待各种观点",
"age": 35,
"occupation": "管理者",
"personality_traits": ["中立", "平衡", "包容"],
"evaluation_focus": ["全面性", "平衡性", "开放性"],
"system_prompt": """
你是一位中立的观察者,能够平衡看待不同观点。
评价评论时,你会关注:
1. 是否考虑了多方面
2. 是否过于偏激
3. 是否尊重不同观点
你认为好的评论应该理性、开放、有包容性。
"""
},
"实用主义者": {
"name": "实用主义者",
"description": "关注实际用途,看重可操作性",
"age": 27,
"occupation": "创业者",
"personality_traits": ["务实", "效率优先", "结果导向"],
"evaluation_focus": ["实用价值", "可操作性", "效率"],
"system_prompt": """
你是一位实用主义者,看重实际价值。
评价评论时,你会关注:
1. 是否提供了有用的信息或建议
2. 是否可以实际应用
3. 是否简洁高效
你不喜欢空洞的抒情或没有实质内容的评论。
"""
}
}
@classmethod
def get_persona(cls, persona_name: str) -> dict:
"""获取指定人设"""
return cls.PERSONAS.get(persona_name)
@classmethod
def get_all_personas(cls) -> list:
"""获取所有人设列表"""
return list(cls.PERSONAS.keys())
评估Prompt模板:
# services/evaluation_prompts.py
class EvaluationPrompts:
"""评估相关的Prompt模板"""
EVALUATION_TEMPLATE = """
【任务】请以"{persona_name}"的身份,评价以下社交媒体评论。
【你的人设】
{persona_description}
{system_prompt}
【原帖内容】
标题:{post_title}
内容:{post_content}
分类:{post_category}
【待评价的评论】
{comment_content}
(评论风格:{comment_style})
【评价要求】
请从以下维度给出评分(1-5分,5分最高):
1. 内容相关性:评论与帖子内容的相关程度
2. 情感共鸣:是否能引起情感共鸣
3. 讨论价值:是否能引发有意义的讨论
4. 表达质量:语言表达的流畅度和准确性
然后,给出你的态度(从以下选择一个):
- like(点赞):认为这是一条好评论
- neutral(中立):评论还可以,但不突出
- dislike(踩):认为这条评论有明显问题
最后,用1-2句话简要说明你的理由。
请严格按照以下JSON格式输出(不要有其他内容):
{{
"relevance_score": 评分(1-5的整数),
"emotional_score": 评分(1-5的整数),
"discussion_score": 评分(1-5的整数),
"quality_score": 评分(1-5的整数),
"action": "like/neutral/dislike",
"feedback": "你的评价理由(50字以内)"
}}
"""
@classmethod
def build_evaluation_prompt(
cls,
persona: dict,
post_title: str,
post_content: str,
post_category: str,
comment_content: str,
comment_style: str
) -> str:
"""构建评估Prompt"""
return cls.EVALUATION_TEMPLATE.format(
persona_name=persona["name"],
persona_description=persona["description"],
system_prompt=persona["system_prompt"],
post_title=post_title,
post_content=post_content,
post_category=post_category,
comment_content=comment_content,
comment_style=comment_style
)
检查点:
- 8个Agent人设设计完成
- 评估Prompt模板完成
- 能用一个Agent成功评价一条评论
Day 15-17: 多智能体评估服务实现 #
# services/agent_evaluator.py
import json
from typing import List, Dict
from .agent_personas import AgentPersonas
from .evaluation_prompts import EvaluationPrompts
from ..utils.llm_client import LLMClient
class AgentEvaluator:
"""多智能体评估服务(核心创新模块)"""
def __init__(self):
self.llm_client = LLMClient()
self.personas = AgentPersonas()
self.prompts = EvaluationPrompts()
def evaluate_comment_by_agent(
self,
persona_name: str,
post_title: str,
post_content: str,
post_category: str,
comment_content: str,
comment_style: str
) -> Dict:
"""单个Agent评估单条评论"""
# 获取人设
persona = self.personas.get_persona(persona_name)
if not persona:
raise ValueError(f"Unknown persona: {persona_name}")
# 构建评估Prompt
prompt = self.prompts.build_evaluation_prompt(
persona=persona,
post_title=post_title,
post_content=post_content,
post_category=post_category,
comment_content=comment_content,
comment_style=comment_style
)
# 调用LLM进行评估
response = self.llm_client.chat_completion(
messages=[
{"role": "system", "content": persona["system_prompt"]},
{"role": "user", "content": prompt}
],
temperature=0.5 # 评估阶段用中等温度
)
# 解析结果
try:
evaluation = json.loads(response)
# 计算综合分数
evaluation["overall_score"] = (
evaluation["relevance_score"] +
evaluation["emotional_score"] +
evaluation["discussion_score"] +
evaluation["quality_score"]
) / 4.0
except json.JSONDecodeError:
# 解析失败,使用默认值
evaluation = {
"relevance_score": 3,
"emotional_score": 3,
"discussion_score": 3,
"quality_score": 3,
"overall_score": 3.0,
"action": "neutral",
"feedback": "评估失败,使用默认值"
}
evaluation["agent_persona"] = persona_name
return evaluation
def evaluate_comment_by_multiple_agents(
self,
comment_id: int,
post_title: str,
post_content: str,
post_category: str,
comment_content: str,
comment_style: str,
agent_names: List[str] = None
) -> List[Dict]:
"""多个Agent评估同一条评论"""
if agent_names is None:
# 默认使用所有Agent
agent_names = self.personas.get_all_personas()
evaluations = []
for agent_name in agent_names:
try:
evaluation = self.evaluate_comment_by_agent(
persona_name=agent_name,
post_title=post_title,
post_content=post_content,
post_category=post_category,
comment_content=comment_content,
comment_style=comment_style
)
evaluation["comment_id"] = comment_id
evaluations.append(evaluation)
except Exception as e:
print(f"Agent {agent_name} 评估失败: {e}")
continue
return evaluations
def analyze_evaluation_results(self, evaluations: List[Dict]) -> Dict:
"""分析评估结果,生成统计报告"""
if not evaluations:
return {}
# 统计各维度平均分
avg_scores = {
"relevance": sum(e["relevance_score"] for e in evaluations) / len(evaluations),
"emotional": sum(e["emotional_score"] for e in evaluations) / len(evaluations),
"discussion": sum(e["discussion_score"] for e in evaluations) / len(evaluations),
"quality": sum(e["quality_score"] for e in evaluations) / len(evaluations),
"overall": sum(e["overall_score"] for e in evaluations) / len(evaluations)
}
# 统计行为分布
actions = {"like": 0, "neutral": 0, "dislike": 0}
for e in evaluations:
actions[e["action"]] = actions.get(e["action"], 0) + 1
# 计算争议指数(标准差)
import statistics
overall_scores = [e["overall_score"] for e in evaluations]
controversy_index = statistics.stdev(overall_scores) if len(overall_scores) > 1 else 0
# 找出最高分和最低分的Agent
sorted_evals = sorted(evaluations, key=lambda x: x["overall_score"])
return {
"average_scores": avg_scores,
"action_distribution": actions,
"controversy_index": controversy_index,
"total_agents": len(evaluations),
"like_rate": actions["like"] / len(evaluations),
"highest_rating_agent": {
"name": sorted_evals[-1]["agent_persona"],
"score": sorted_evals[-1]["overall_score"],
"feedback": sorted_evals[-1]["feedback"]
},
"lowest_rating_agent": {
"name": sorted_evals[0]["agent_persona"],
"score": sorted_evals[0]["overall_score"],
"feedback": sorted_evals[0]["feedback"]
}
}
API接口:
# api/evaluations.py
@router.post("/evaluate", response_model=schemas.EvaluationResponse)
def evaluate_comment(
request: schemas.EvaluationRequest,
db: Session = Depends(get_db)
):
"""评估评论"""
# 获取评论和帖子
comment = db.query(models.Comment).filter(
models.Comment.id == request.comment_id
).first()
if not comment:
raise HTTPException(status_code=404, detail="Comment not found")
post = comment.post
# 多Agent评估
evaluator = AgentEvaluator()
evaluations_data = evaluator.evaluate_comment_by_multiple_agents(
comment_id=comment.id,
post_title=post.title,
post_content=post.content,
post_category=post.category,
comment_content=comment.content,
comment_style=comment.style,
agent_names=request.agent_names
)
# 保存评估结果
db_evaluations = []
for eval_data in evaluations_data:
db_eval = models.Evaluation(
comment_id=comment.id,
agent_persona=eval_data["agent_persona"],
relevance_score=eval_data["relevance_score"],
emotional_score=eval_data["emotional_score"],
discussion_score=eval_data["discussion_score"],
quality_score=eval_data["quality_score"],
overall_score=eval_data["overall_score"],
action=eval_data["action"],
feedback=eval_data["feedback"]
)
db.add(db_eval)
db_evaluations.append(db_eval)
db.commit()
# 分析结果
analysis = evaluator.analyze_evaluation_results(evaluations_data)
return {
"comment_id": comment.id,
"evaluations": db_evaluations,
"analysis": analysis
}
@router.get("/comments/{comment_id}/analysis", response_model=schemas.EvaluationAnalysis)
def get_evaluation_analysis(comment_id: int, db: Session = Depends(get_db)):
"""获取评论的评估分析"""
comment = db.query(models.Comment).filter(
models.Comment.id == comment_id
).first()
if not comment:
raise HTTPException(status_code=404, detail="Comment not found")
evaluations = db.query(models.Evaluation).filter(
models.Evaluation.comment_id == comment_id
).all()
if not evaluations:
raise HTTPException(status_code=404, detail="No evaluations found")
# 转换为字典格式
evaluations_data = [
{
"agent_persona": e.agent_persona,
"relevance_score": e.relevance_score,
"emotional_score": e.emotional_score,
"discussion_score": e.discussion_score,
"quality_score": e.quality_score,
"overall_score": e.overall_score,
"action": e.action,
"feedback": e.feedback
}
for e in evaluations
]
evaluator = AgentEvaluator()
analysis = evaluator.analyze_evaluation_results(evaluations_data)
return {
"comment": comment,
"evaluations": evaluations,
"analysis": analysis
}
检查点:
- 能用多个Agent评估一条评论
- 评估结果保存到数据库
- 能生成评估分析报告
- API返回正常
第三阶段:前端开发与系统集成(3月16日-4月5日,21天) #
Week 4-5: 前端界面开发 #
Day 18-22: 核心页面实现 #
1. 帖子管理页面
// src/pages/PostManagement.tsx
import React, { useState, useEffect } from 'react';
import { Table, Button, Modal, Form, Input, Select, message, Space, Tag } from 'antd';
import { PlusOutlined, DeleteOutlined, EditOutlined } from '@ant-design/icons';
import axios from 'axios';
const PostManagement: React.FC = () => {
const [posts, setPosts] = useState([]);
const [loading, setLoading] = useState(false);
const [modalVisible, setModalVisible] = useState(false);
const [form] = Form.useForm();
// 加载帖子列表
const loadPosts = async () => {
setLoading(true);
try {
const res = await axios.get('http://localhost:8000/api/posts');
setPosts(res.data);
} catch (error) {
message.error('加载失败');
}
setLoading(false);
};
useEffect(() => {
loadPosts();
}, []);
// 创建帖子
const handleCreate = async (values: any) => {
try {
await axios.post('http://localhost:8000/api/posts', values);
message.success('创建成功');
setModalVisible(false);
form.resetFields();
loadPosts();
} catch (error) {
message.error('创建失败');
}
};
const columns = [
{
title: 'ID',
dataIndex: 'id',
width: 60,
},
{
title: '标题',
dataIndex: 'title',
width: 200,
},
{
title: '内容',
dataIndex: 'content',
ellipsis: true,
},
{
title: '分类',
dataIndex: 'category',
width: 120,
render: (category: string) => <Tag color="blue">{category}</Tag>,
},
{
title: '创建时间',
dataIndex: 'created_at',
width: 180,
},
{
title: '操作',
width: 150,
render: (record: any) => (
<Space>
<Button type="link" href={`/comment-generation/${record.id}`}>
生成评论
</Button>
</Space>
),
},
];
return (
<div>
<div style={{ marginBottom: 16 }}>
<Button type="primary" icon={<PlusOutlined />} onClick={() => setModalVisible(true)}>
新建帖子
</Button>
</div>
<Table
columns={columns}
dataSource={posts}
loading={loading}
rowKey="id"
/>
<Modal
title="新建帖子"
open={modalVisible}
onCancel={() => setModalVisible(false)}
onOk={() => form.submit()}
>
<Form form={form} onFinish={handleCreate} layout="vertical">
<Form.Item
name="title"
label="标题"
rules={[{ required: true, message: '请输入标题' }]}
>
<Input placeholder="请输入帖子标题" />
</Form.Item>
<Form.Item
name="content"
label="内容"
rules={[{ required: true, message: '请输入内容' }]}
>
<Input.TextArea rows={6} placeholder="请输入帖子内容" />
</Form.Item>
<Form.Item
name="category"
label="分类"
rules={[{ required: true, message: '请选择分类' }]}
>
<Select>
<Select.Option value="时事热点">时事热点</Select.Option>
<Select.Option value="科技产品">科技产品</Select.Option>
<Select.Option value="娱乐八卦">娱乐八卦</Select.Option>
<Select.Option value="生活分享">生活分享</Select.Option>
<Select.Option value="争议话题">争议话题</Select.Option>
</Select>
</Form.Item>
<Form.Item name="author" label="作者">
<Input placeholder="可选" />
</Form.Item>
</Form>
</Modal>
</div>
);
};
export default PostManagement;
2. 评论生成页面
// src/pages/CommentGeneration.tsx
import React, { useState, useEffect } from 'react';
import { Card, Button, Select, InputNumber, List, Tag, Space, message, Spin } from 'antd';
import { useParams } from 'react-router-dom';
import axios from 'axios';
const CommentGeneration: React.FC = () => {
const { postId } = useParams();
const [post, setPost] = useState<any>(null);
const [comments, setComments] = useState([]);
const [loading, setLoading] = useState(false);
const [selectedStyles, setSelectedStyles] = useState(['幽默型', '理性型', '情感共鸣型']);
const [countPerStyle, setCountPerStyle] = useState(1);
// 加载帖子详情
useEffect(() => {
const loadPost = async () => {
try {
const res = await axios.get(`http://localhost:8000/api/posts/${postId}`);
setPost(res.data);
setComments(res.data.comments || []);
} catch (error) {
message.error('加载失败');
}
};
loadPost();
}, [postId]);
// 生成评论
const handleGenerate = async () => {
setLoading(true);
try {
const res = await axios.post('http://localhost:8000/api/comments/generate', {
post_id: parseInt(postId),
styles: selectedStyles,
count_per_style: countPerStyle
});
setComments(res.data.comments);
message.success(`成功生成${res.data.count}条评论`);
} catch (error) {
message.error('生成失败');
}
setLoading(false);
};
// 评估评论
const handleEvaluate = async (commentId: number) => {
try {
await axios.post('http://localhost:8000/api/evaluations/evaluate', {
comment_id: commentId
});
message.success('评估完成');
// 跳转到评估结果页面
window.location.href = `/evaluation-result/${commentId}`;
} catch (error) {
message.error('评估失败');
}
};
if (!post) {
return <Spin />;
}
return (
<div>
<Card title="原帖内容" style={{ marginBottom: 16 }}>
<h3>{post.title}</h3>
<p>{post.content}</p>
<Tag color="blue">{post.category}</Tag>
</Card>
<Card title="生成设置" style={{ marginBottom: 16 }}>
<Space direction="vertical" style={{ width: '100%' }}>
<div>
<span>评论风格:</span>
<Select
mode="multiple"
style={{ width: '100%' }}
value={selectedStyles}
onChange={setSelectedStyles}
options={[
{ label: '幽默型', value: '幽默型' },
{ label: '理性型', value: '理性型' },
{ label: '情感共鸣型', value: '情感共鸣型' },
{ label: '争议型', value: '争议型' },
{ label: '支持型', value: '支持型' },
]}
/>
</div>
<div>
<span>每种风格生成数量:</span>
<InputNumber min={1} max={5} value={countPerStyle} onChange={setCountPerStyle} />
</div>
<Button type="primary" onClick={handleGenerate} loading={loading}>
生成评论
</Button>
</Space>
</Card>
<Card title={`生成的评论(${comments.length}条)`}>
<List
dataSource={comments}
renderItem={(comment: any) => (
<List.Item
actions={[
<Button type="link" onClick={() => handleEvaluate(comment.id)}>
评估
</Button>
]}
>
<List.Item.Meta
title={<Tag color="green">{comment.style}</Tag>}
description={comment.content}
/>
</List.Item>
)}
/>
</Card>
</div>
);
};
export default CommentGeneration;
3. 评估结果可视化页面(重点)
// src/pages/EvaluationResult.tsx
import React, { useState, useEffect } from 'react';
import { Card, Row, Col, Table, Tag, Spin, Statistic } from 'antd';
import { LikeOutlined, DislikeOutlined, MinusOutlined } from '@ant-design/icons';
import { useParams } from 'react-router-dom';
import { Radar, Bar } from 'recharts';
import axios from 'axios';
const EvaluationResult: React.FC = () => {
const { commentId } = useParams();
const [data, setData] = useState<any>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const loadData = async () => {
try {
const res = await axios.get(`http://localhost:8000/api/evaluations/comments/${commentId}/analysis`);
setData(res.data);
} catch (error) {
console.error(error);
}
setLoading(false);
};
loadData();
}, [commentId]);
if (loading) {
return <Spin />;
}
if (!data) {
return <div>加载失败</div>;
}
const { comment, evaluations, analysis } = data;
// 准备雷达图数据
const radarData = [
{ dimension: '内容相关性', score: analysis.average_scores.relevance },
{ dimension: '情感共鸣', score: analysis.average_scores.emotional },
{ dimension: '讨论价值', score: analysis.average_scores.discussion },
{ dimension: '表达质量', score: analysis.average_scores.quality },
];
const columns = [
{
title: 'Agent',
dataIndex: 'agent_persona',
width: 150,
},
{
title: '相关性',
dataIndex: 'relevance_score',
width: 80,
},
{
title: '情感',
dataIndex: 'emotional_score',
width: 80,
},
{
title: '讨论',
dataIndex: 'discussion_score',
width: 80,
},
{
title: '质量',
dataIndex: 'quality_score',
width: 80,
},
{
title: '综合',
dataIndex: 'overall_score',
width: 80,
render: (score: number) => score.toFixed(2),
},
{
title: '态度',
dataIndex: 'action',
width: 100,
render: (action: string) => {
const config = {
like: { icon: <LikeOutlined />, color: 'success' },
dislike: { icon: <DislikeOutlined />, color: 'error' },
neutral: { icon: <MinusOutlined />, color: 'default' },
};
return <Tag color={config[action].color} icon={config[action].icon}>{action}</Tag>;
},
},
{
title: '评价',
dataIndex: 'feedback',
},
];
return (
<div>
<Card title="待评估评论" style={{ marginBottom: 16 }}>
<Tag color="green">{comment.style}</Tag>
<p style={{ marginTop: 8 }}>{comment.content}</p>
</Card>
<Row gutter={16} style={{ marginBottom: 16 }}>
<Col span={6}>
<Card>
<Statistic
title="综合评分"
value={analysis.average_scores.overall}
precision={2}
suffix="/ 5.0"
/>
</Card>
</Col>
<Col span={6}>
<Card>
<Statistic
title="点赞率"
value={analysis.like_rate * 100}
precision={1}
suffix="%"
valueStyle={{ color: '#3f8600' }}
/>
</Card>
</Col>
<Col span={6}>
<Card>
<Statistic
title="争议指数"
value={analysis.controversy_index}
precision={2}
/>
</Card>
</Col>
<Col span={6}>
<Card>
<Statistic
title="参与Agent"
value={analysis.total_agents}
suffix="个"
/>
</Card>
</Col>
</Row>
<Row gutter={16} style={{ marginBottom: 16 }}>
<Col span={12}>
<Card title="多维度评分雷达图">
{/* 使用Recharts或ECharts绘制雷达图 */}
<div>雷达图占位</div>
</Card>
</Col>
<Col span={12}>
<Card title="行为分布">
{/* 使用柱状图展示like/neutral/dislike分布 */}
<div>柱状图占位</div>
</Card>
</Col>
</Row>
<Card title="极端评价">
<Row gutter={16}>
<Col span={12}>
<Card type="inner" title="最高评分">
<p><strong>{analysis.highest_rating_agent.name}</strong></p>
<p>评分:{analysis.highest_rating_agent.score.toFixed(2)}</p>
<p>{analysis.highest_rating_agent.feedback}</p>
</Card>
</Col>
<Col span={12}>
<Card type="inner" title="最低评分">
<p><strong>{analysis.lowest_rating_agent.name}</strong></p>
<p>评分:{analysis.lowest_rating_agent.score.toFixed(2)}</p>
<p>{analysis.lowest_rating_agent.feedback}</p>
</Card>
</Col>
</Row>
</Card>
<Card title="详细评估结果" style={{ marginTop: 16 }}>
<Table
columns={columns}
dataSource={evaluations}
rowKey="id"
pagination={false}
/>
</Card>
</div>
);
};
export default EvaluationResult;
检查点:
- 三个核心页面开发完成
- 前后端联调成功
- UI美观、交互流畅
- 能完整走通"创建帖子→生成评论→评估→查看结果"流程
第四阶段:测试与论文撰写(3月16日-4月25日) #
并行任务1:系统测试(3月20日-3月25日) #
功能测试 #
测试用例表格:
| 测试ID | 测试模块 | 测试用例 | 输入 | 预期输出 | 实际输出 | 结果 |
|---|---|---|---|---|---|---|
| TC001 | 帖子管理 | 创建帖子 | 标题、内容、分类 | 成功创建,返回ID | … | ✅ |
| TC002 | 评论生成 | 生成幽默型评论 | 帖子ID,风格=幽默型 | 返回1条幽默评论 | … | ✅ |
| TC003 | 评论生成 | 批量生成 | 3种风格,每种2条 | 返回6条评论 | … | ✅ |
| TC004 | Agent评估 | 单Agent评估 | 评论ID,Agent=资深爱好者 | 返回评分和反馈 | … | ✅ |
| TC005 | Agent评估 | 多Agent评估 | 评论ID,8个Agent | 返回8份评估结果 | … | ✅ |
| … | … | … | … | … | … | … |
性能测试 #
# tests/performance_test.py
import time
import asyncio
from services.comment_generator import CommentGenerator
def test_generation_time():
"""测试评论生成耗时"""
generator = CommentGenerator()
start = time.time()
comment = generator.generate_comment(
post_content="测试帖子内容",
post_title="测试标题",
category="时事热点",
style="幽默型"
)
end = time.time()
print(f"单条评论生成耗时: {end - start:.2f}秒")
assert end - start < 10, "生成时间过长"
def test_batch_evaluation_time():
"""测试批量评估耗时"""
from services.agent_evaluator import AgentEvaluator
evaluator = AgentEvaluator()
start = time.time()
evaluations = evaluator.evaluate_comment_by_multiple_agents(
comment_id=1,
post_title="测试",
post_content="测试内容",
post_category="科技产品",
comment_content="这是一条测试评论",
comment_style="理性型"
)
end = time.time()
print(f"8个Agent评估耗时: {end - start:.2f}秒")
检查点:
- 所有功能测试用例通过
- 性能测试数据记录(用于论文)
- 截图保存(用于论文)
并行任务2:论文撰写(边开发边写) #
详见《论文大纲.md》
第五阶段:论文完善与答辩准备(4月6日-5月底) #
4月6日-4月20日:论文初稿完成 #
- 完成第1-6章全部内容
- 图表制作完成(30+张)
- 参考文献整理(20篇)
- 字数达到15000字以上
4月21日-4月30日:查重与修改 #
- 提交知网查重(重复率<30%)
- 根据查重结果修改
- 给导师审阅
- 根据导师意见修改
5月1日-5月20日:论文定稿 #
- 完成所有修改
- 格式调整(严格按照学校规范)
- 打印装订
5月21日-5月31日:答辩准备 #
答辩PPT大纲:
- 封面(1页)
- 研究背景与意义(2页)
- 系统架构设计(2页)
- 核心功能演示(8页):
- 评论生成(3页)
- 多Agent评估(5页)⭐重点
- 实验结果与分析(3页)
- 总结与展望(1页)
系统演示准备:
- 准备3-5个典型案例
- 录制演示视频(备用)
- 准备可能的提问回答
关键里程碑时间节点 #
| 日期 | 里程碑 | 检查点 |
|---|---|---|
| 3月3日 | 框架搭建完成 | 前后端能跑起来 |
| 3月10日 | 评论生成模块完成 | 能生成5种风格评论 |
| 3月15日 | MVP完成 | 核心功能全部实现 |
| 3月25日 | 完整版完成 | 前端可视化完成 |
| 4月5日 | 测试完成 | 所有实验数据收集完毕 |
| 4月20日 | 论文初稿 | 15000字,提交给导师 |
| 5月5日 | 论文定稿 | 查重通过,格式正确 |
| 5月25日 | 答辩准备完成 | PPT+演示视频 |
风险管理 #
风险1:LLM API调用失败/超时 #
应对:
- 添加重试机制(3次)
- 设置超时时间(30秒)
- 准备备用API(多个模型切换)
风险2:生成质量不稳定 #
应对:
- 优化Prompt模板
- 调整temperature参数
- 增加Few-shot示例
风险3:开发进度延误 #
应对:
- MVP优先,保证核心功能
- 降低部分功能的复杂度
- 每周检查进度,及时调整
风险4:论文查重率过高 #
应对:
- 技术介绍用自己的话重新组织
- 多引用、多标注
- 预留充足修改时间
每周检查清单 #
每周日晚上复盘:
- 本周计划任务完成情况
- 遇到的问题及解决方案
- 下周计划调整
- 论文进度同步
提醒:
- 每天备份代码(Git push)
- 随时截图保存(论文用)
- 记录实验数据
- 遇到问题及时求助(导师/同学/AI)
资源清单 #
开发资源 #
- OpenAI API key(或其他LLM API)
- 服务器/云主机(可选)
- 域名(可选)
学习资源 #
- FastAPI官方文档
- React官方文档
- Ant Design组件库文档
- Prompt Engineering指南
论文资源 #
- 参考文献(已在开题报告中)
- LaTeX模板(如果学校要求)
- 论文查重系统账号
最后建议:
- 不要追求完美,MVP优先
- 核心创新点(多Agent评估)要做深做透
- 边开发边记录,边写论文
- 定期和导师沟通
- 保持健康作息,不要熬夜
加油!3月中旬见! 🎯