基于大语言模型的学生用户画像构建和个性化推荐方法
基于 LLM 的用户画像分析:通义千问 + Prompt Engineering 实践
本文范围: 只讨论 LLM 方法构建学生用户画像。在
outputs/cleaned/已清洗数据之上,调用通义千问生成结构化画像。不包含 原始清洗与规则画像方法。
摘要: 将学生学业、考勤、消费等指标组装为 Prompt,通过 DashScope 调用 qwen-plus,强制 JSON 输出,再解析为 CSV、画像卡片 txt 与统计图表。
一、为什么用 LLM 做用户画像
传统的学生画像方法主要依赖 规则引擎 + 统计阈值。例如,设定“平均分 < 60 → 成绩待提升”、“考勤异常 > 3次 → 行为需关注”等硬性规则。这种方式虽然稳定、可解释性强,但在面对复杂、多维的学生数据时,暴露出两个核心局限:
- 标签碎片化,缺乏整体叙事:规则生成的标签往往是孤立的(如“数学薄弱”、“消费偏高”),难以自动将这些点状信息串联成一个有逻辑、有故事线的完整学生画像。管理者看到的是一堆标签,而非一个立体的“人”。
- 难以生成深度的自然语言洞察:规则系统可以输出“是什么”(如“高风险”),但很难自动回答“为什么是这个画像”以及“下一步具体怎么做”。这部分的解读和报告撰写仍需大量人工介入,效率低下。
LLM(大语言模型)的引入,正是为了弥补这些短板。 大模型的核心能力在于 理解结构化数据、进行综合推理、并生成连贯的自然语言结论。在本实践中,我们构建的核心链路是:
清洗后的学生指标 → Prompt 设计 → 通义千问 API → JSON 解析 → 画像卡片 + 图表
这条链路的优势在于:
- 整体性分析:LLM 能同时考虑学业、行为、消费等多个维度,输出一个综合性的评价(如“艺体特长但理科基础薄弱的波动型学习者”),而非一堆割裂的标签。
- 可解释的叙事:通过精心设计的 Prompt,可以要求模型不仅给出结论,还要提供推理依据和个性化的改进建议,生成一段120-180字的“完整画像描述”,极大提升了报告的可读性和 actionable insight(可执行洞察)。
- 灵活适配:当分析维度或评价标准需要调整时,通常只需修改 Prompt 指令,而无需重写复杂的规则代码,迭代成本更低。
因此,LLM 并非要取代传统的数据清洗与特征工程,而是作为其之上的“认知层”,将冰冷的数据转化为有温度、有逻辑、可直接用于沟通和决策的叙事报告。
二、整体架构
outputs/cleaned/student_profile.csv
outputs/cleaned/clean_score.csv
↓
load_student_features() # 补偏科指数、分科摘要、日均消费等
↓
build_student_prompt() # Prompt:角色 + 数据 + 任务 + JSON 格式
↓
call_qwen() # DashScope 调用 qwen-plus
↓
_extract_json() / _normalize_result()
↓
format_portrait_card() # 生成可读 txt 卡片
↓
student_portrait_qwen.csv
student_portrait_qwen_cards.txt
outputs/analysis/qwen_figures/
对应脚本:qwen_portrait.py
三、输入数据
LLM 读的是 学生级宽表,不是原始流水。主要字段:
| 维度 | 字段 | 用途 |
|---|---|---|
| 学籍 | 姓名、班级、性别 | 画像抬头 |
| 学业 | 平均成绩、成绩标准差、偏科指数 | 学业等级、学习态度 |
| 分科 | subject_summary | 学科特征(优势/薄弱科目) |
| 考勤 | 迟到、早退、考勤异常合计 | 行为模式 |
| 消费 | 日均消费、消费次数 | 生活规律 |
其中 subject_summary 由程序从成绩表自动生成,例如:
相对优势学科:音乐(90.0分)、美术(82.0分)、英语(62.3分);
相对薄弱学科:地理(49.6分)、体育(19.2分)、技术(13.9分)
对应代码(节选):
def _build_subject_summary(student_id, score_df):
sub = score_df[(score_df["bf_StudentID"] == student_id) & score_df["mes_Score"].notna()]
means = sub.groupby("mes_sub_name")["mes_Score"].mean().sort_values(ascending=False)
top = "、".join(f"{n}({s:.1f}分)" for n, s in means.head(3).items())
bottom = "、".join(f"{n}({s:.1f}分)" for n, s in means.tail(3).items())
return f"相对优势学科:{top};相对薄弱学科:{bottom}"
四、Prompt 设计
采用 「角色 + 数据 + 任务 + JSON 格式」 四段式。
角色: 熟悉学生管理与学业诊断的数据分析专家。
输出字段:
| 字段 | 含义 |
|---|---|
academic_level | 学业等级 |
subject_profile | 学科特征 |
learning_attitude | 学习态度 |
behavior_pattern | 行为模式 |
strengths / weaknesses | 优势 / 待改进 |
suggestions | 建议 |
full_portrait | 120~180 字完整描述 |
portrait_tags | 3~5 个短标签 |
qwen_risk_level | 低/中/高风险 |
JSON 输出示例:
{
"academic_level": "中等偏下",
"subject_profile": "偏艺体型,音乐美术突出,技术体育薄弱",
"learning_attitude": "成绩波动大,专注度不够稳定",
"behavior_pattern": "消费规律,偶有考勤异常",
"strengths": ["艺术感知力强", "消费自律"],
"weaknesses": ["理科基础薄弱", "成绩波动大"],
"suggestions": ["补足薄弱学科基础", "建立周复盘机制"],
"full_portrait": "一段完整画像描述...",
"portrait_tags": ["艺体特长", "波动型学习者"],
"qwen_risk_level": "中风险"
}
Prompt 构建思路(节选):
def build_student_prompt(row):
fields = [
("姓名", row["bf_Name"]), ("班级", row["cla_Name"]),
("平均成绩", row["avg_score"]), ("成绩标准差", row["score_std"]),
("分科情况", row["subject_summary"]),
("考勤异常次数", row["attendance_abnormal"]),
("日均消费", row["daily_avg_spend"]),
]
student_block = "\n".join(f"{k}: {v}" for k, v in fields)
return f"你是学生管理分析专家...\n【学生数据】\n{student_block}\n...仅输出 JSON..."
五、通义千问 API 调用
import dashscope
from dashscope import Generation
dashscope.api_key = os.getenv("DASHSCOPE_API_KEY")
response = Generation.call(
model="qwen-plus",
messages=[{"role": "user", "content": prompt}],
result_format="message",
temperature=0.3,
)
content = response.output.choices[0].message.content
说明:
- temperature=0.3:输出更稳定;
- API Key 写在
.env:DASHSCOPE_API_KEY=sk-xxx; - 支持批量并发:
python qwen_portrait.py --limit 30 --batch-size 3 --workers 3
六、JSON 解析与字段标准化
模型返回可能是纯 JSON,也可能带 markdown 包裹,需要容错:
def _extract_json(text):
text = text.strip()
fence = re.search(r"```(?:json)?\s*([\s\S]*?)\s*```", text)
if fence:
text = fence.group(1).strip()
return json.loads(text)
def _normalize_result(raw):
return {
"qwen_academic_level": raw.get("academic_level", ""),
"qwen_subject_profile": raw.get("subject_profile", ""),
"qwen_learning_attitude": raw.get("learning_attitude", ""),
"qwen_behavior_pattern": raw.get("behavior_pattern", ""),
"qwen_strengths": "、".join(raw.get("strengths", [])),
"qwen_weaknesses": "、".join(raw.get("weaknesses", [])),
"qwen_suggestions": ";".join(raw.get("suggestions", [])),
"qwen_full_portrait": raw.get("full_portrait", ""),
"qwen_risk_level": raw.get("qwen_risk_level", ""),
}
七、画像卡片输出
解析后生成两类产物:
1. CSV: student_portrait_qwen.csv(结构化字段,便于统计)

2. TXT 卡片: student_portrait_qwen_cards.txt

格式化逻辑(节选):
def format_portrait_card(record):
lines = [
f"学生: {record['bf_Name']}({record['bf_sex']},{record['cla_Name']})",
f"均分: {record['avg_score']:.1f} | 考勤异常: {record['attendance_abnormal']}次",
f" 学业等级: {record['qwen_academic_level']}",
f" 学科特征: {record['qwen_subject_profile']}",
f" 学习态度: {record['qwen_learning_attitude']}",
f" 行为模式: {record['qwen_behavior_pattern']}",
f" 优势: {record['qwen_strengths']}",
f" 待改进: {record['qwen_weaknesses']}",
f" 建议: {record['qwen_suggestions']}",
f" 【完整画像描述】\n {record['qwen_full_portrait']}",
]
return "\n".join(lines)
真实输出示例(脱敏):
学生: 陈某某(女,白-高二(01))
均分: 56.47 | 考勤异常: 2次 | 日均消费: 10.09元
学业等级: 待提升
学科特征: 显著偏艺体型,音乐、美术优势突出,技术体育薄弱
学习态度: 成绩波动剧烈,学习状态不够稳定
行为模式: 消费规律,偶有考勤异常
优势: 艺术感知力强、消费自律
待改进: 核心学科低于及格线、缺考次数偏多
建议: 补足技术地理基础;建立周复盘机制
【完整画像描述】
陈某某整体学业待提升,但艺术禀赋突出。技术仅13.9分,
成绩标准差高达34.65,说明学习状态起伏大。消费与考勤整
体可控,建议聚焦基础补缺与学习节奏重建。
风险等级: 中风险
画像标签: 艺体特长生、基础薄弱型、波动型学习者
八、可视化
基于 LLM 结果自动生成 14 张图,目录:outputs/analysis/qwen_figures/
| 图 | 文件 | 说明 |
|---|---|---|
| 风险分布 | 01_qwen_risk_distribution_pie.png | 低/中/高风险占比 |
| 学业等级 | 02_academic_level_pie.png | 学业等级分布 |
| 待改进主题 | 05_weakness_themes_bar.png | 偏科、波动等主题 |
| 成绩-风险 | 07_score_risk_scatter.png | 成绩与波动散点 |
| 画像卡片图 | 11_sample_portrait_card.png | txt 卡片渲染成图 |





只重新出图:
python qwen_portrait.py --plots-only
九、如何复现
pip install dashscope python-dotenv pandas matplotlib
# 1. 清洗数据
python clean.py
# 2. 跑 LLM 画像(默认 30 人)
python qwen_portrait.py
# 3. 小样本试跑
python qwen_portrait.py --limit 5 --batch-size 1
# 4. 不调 API,看格式
python qwen_portrait.py --mock --limit 2
.env 配置:
DASHSCOPE_API_KEY=你的密钥
十、方法小结
| 环节 | 做法 |
|---|---|
| Prompt 设计 | 角色 + 结构化数据 + JSON 约束 |
| LLM 推理 | 通义千问 qwen-plus |
| 结构化输出 | JSON → CSV |
| 画像卡片 | 格式化 txt + 图片渲染 |
| 可视化 | 14 类统计图 |
十一、结语
基于 LLM 的用户画像,不是让大模型替代数据工程,而是:
Python 准备事实 → Prompt 规定分析方式 → JSON 接回系统 → 卡片与图表呈现给人看。
完整实现见 qwen_portrait.py。
声明:文中学生姓名与数据均已脱敏,仅用于技术学习与交流。
更多推荐



所有评论(0)