基于大语言模型的学生用户画像构建与个性化推荐实战

本次实验依托数智教育公开数据集,完成了一套完整的学生多维画像构建+个性化学习资源推荐落地实战。区别于单纯调用大模型生成文本内容的浅层实验,本项目聚焦教育业务真实场景,通过数据清洗、多源数据聚合、特征指标工程、规则建模,结合向量检索技术与大语言模型能力,搭建出一套可复现、可解释、可迭代的智能化教育分析体系,为个性化教学、学生学情干预提供数据支撑。

本次实验的完整技术链路可总结为:读取多维度教育原始数据→统一学生数据粒度→构建学业、行为、生活多维画像指标→搭建传统规则画像基线→借助大模型实现画像自然语言解读→搭建教育资源向量库完成语义召回→结合学生画像与候选资源生成专属个性化学习推荐方案。

本文以标准实验报告体例展开,依次阐述实验设计思路、环境配置、数据处理流程、建模方法、结果分析、技术对比与实验总结,同时附上完整可运行的核心代码与可视化结果解析。

一、实验研究背景与整体设计思路

传统教育学情分析大多仅依托考试成绩单一维度评判学生状态,存在明显局限性。学生学业成绩薄弱,成因具备多样性,既可能是学科基础薄弱、知识点存在短板,也可能与日常考勤散漫、校园生活作息紊乱、学习状态不稳定等行为因素高度相关。单一的成绩评价体系,无法全面刻画学生综合学情,难以实现精准化、个性化的教学辅导。

基于上述痛点,本实验采用多源教育数据融合的核心思路,整合学生基础信息、学业成绩、校园考勤、校园消费四大核心数据,构建全方位学生画像体系。整体实验流程分层清晰、各司其职,具体阶段如下表所示:

实验阶段 输入内容 输出成果 核心作用
数据审计 7份CSV原始数据集 数据表规模、字段释义、缺失值统计报告 校验数据完整性、可用性,判断建模可行性
数据清洗 学生、成绩、考勤、消费流水数据 统一学生粒度的标准化结构化数据 清洗无效数据,统一数据口径,为特征工程奠基
指标工程 各类标准化流水数据 学业、考勤、生活、均衡性等多维量化指数 将原始数据转化为具备业务意义的建模特征
规则画像建模 多维量化指标、业务阈值 学生学情标签、分层分级结果 搭建可解释的传统画像基线模型
LLM智能画像 匿名化学生结构化指标 自然语言学生学情画像解读 提升画像可读性,实现综合学情智能诊断
向量语义检索 学生画像文本、自建教育资源库 高关联候选学习资源集合 突破规则匹配局限,实现语义级资源召回
LLM个性化推荐 学生画像+候选优质资源 定制化学习方案与资源推荐报告 输出可落地、可执行的个性化学习指导策略

本实验核心设计原则:大语言模型仅承担解释与生成任务,不替代基础数据处理与量化建模。先通过代码完成严谨的数据清洗、特征计算、指标建模,保证底层数据与特征的真实性、客观性,再依托大模型完成自然语言解读与个性化内容生成,兼顾模型可控性与内容智能化。

二、数据集整体概况

本次实验数据集共计7份CSV文件,涵盖教师、学生、成绩、考勤、消费等校园全场景数据,完整覆盖学生学习、行为、生活三大维度,各文件具体用途如下:

数据文件名称 数据含义 核心使用用途
1_teacher.csv 教师任课信息数据 辅助梳理班级、课程、教师关联关系,辅助学情背景分析
2_student_info.csv 学生基础信息数据 提供学生ID、性别、班级、住宿等基础属性,作为主表数据
3_kaoqin.csv 学生考勤流水数据 统计各类考勤异常行为,构建考勤健康评价指标
4_kaoqintype.csv 考勤类型分类数据 界定考勤事件类别,规范考勤数据统计口径
5_chengji.csv 学生考试成绩流水数据 构建学业表现、学习稳定性、学科强弱项核心指标
6_exam_type.csv 考试类型说明数据 区分不同考试场景,保证成绩分析的合理性
7_consumption.csv 学生校园消费流水数据 挖掘学生生活节奏、校园活跃度,构建生活行为指标

其中,成绩、考勤、消费三份流水数据表为核心建模数据,原始数据均为单条行为记录,无法直接用于学生维度画像分析,必须经过数据清洗、聚合、归一化处理,统一至学生ID单一粒度。

三、实验环境配置与初始化

本次实验基于Python实现,依托数据分析、可视化、大模型调用、向量数据库等第三方库完成全流程开发。为避免系统盘占用、解决中文乱码问题、保障API密钥安全,统一规范路径与环境参数配置,核心初始化代码如下:

import os
import json
import warnings
from pathlib import Path

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import font_manager
from IPython.display import display, Markdown

# 屏蔽冗余警告,优化控制台输出
warnings.filterwarnings("ignore")
# 设置表格展示最大列数、宽度,适配数据查看
pd.set_option("display.max_columns", 80)
pd.set_option("display.width", 140)
pd.set_option("display.max_colwidth", 120)

# 定义实验根目录,兼容不同运行环境
EXPERIMENT_DIR = Path.cwd()
if not (EXPERIMENT_DIR / "数智教育数据集").exists():
    EXPERIMENT_DIR = Path(r"F:\ProjectOfAll\商业数据分析课程\实验7")

# 数据存储路径与结果输出路径定义
DATA_DIR = EXPERIMENT_DIR / "数智教育数据集"
OUTPUT_DIR = EXPERIMENT_DIR / "original_report_output"
OUTPUT_DIR.mkdir(exist_ok=True)

# 全局环境资源路径
F_ENV_ROOT = Path(r"F:\EnvironmentsAndProducttools")

# 配置中文字体,解决可视化乱码问题
font_path = EXPERIMENT_DIR / "SimHei.ttf"
if font_path.exists():
    font_manager.fontManager.addfont(str(font_path))
    plt.rcParams["font.sans-serif"] = ["SimHei", "Microsoft YaHei", "Arial Unicode MS", "DejaVu Sans"]
else:
    plt.rcParams["font.sans-serif"] = ["Microsoft YaHei", "SimHei", "Arial Unicode MS", "DejaVu Sans"]

# 配置可视化参数
plt.rcParams["axes.unicode_minus"] = False
plt.rcParams["figure.dpi"] = 120

# 从环境变量读取千问API密钥,避免硬编码泄露
os.getenv("DASHSCOPE_API_KEY")

通过环境变量读取API密钥的方式,可有效避免代码、报告、导出文件中出现私密密钥,适配实验分享与作业提交场景,安全性更高。

四、数据读取与数据完整性审计

不同CSV文件存在编码、分隔符差异,直接读取易出现解码报错。为提升代码鲁棒性,自定义自适应编码读取函数,自动适配utf-8、gbk、gb18030三种常用编码格式,批量读取全部数据集并完成数据审计。

def read_csv_smart(path: Path, **kwargs) -> pd.DataFrame:
    """自适应编码读取CSV文件,规避解码错误"""
    last_error = None
    for enc in ("utf-8", "gbk", "gb18030"):
        try:
            return pd.read_csv(path, encoding=enc, **kwargs)
        except UnicodeDecodeError as exc:
            last_error = exc
    raise last_error

# 批量读取所有数据表
tables = {
    "teacher": read_csv_smart(DATA_DIR / "1_teacher.csv"),
    "student": read_csv_smart(DATA_DIR / "2_student_info.csv"),
    "attendance": read_csv_smart(DATA_DIR / "3_kaoqin.csv"),
    "attendance_type": read_csv_smart(DATA_DIR / "4_kaoqintype.csv", sep="\t"),
    "score": read_csv_smart(DATA_DIR / "5_chengji.csv"),
    "exam_type": read_csv_smart(DATA_DIR / "6_exam_type.csv"),
    "consumption": read_csv_smart(DATA_DIR / "7_consumption.csv"),
}

# 批量统计各表基础信息,完成数据审计
overview_rows = []
for name, df in tables.items():
    id_cols = [c for c in df.columns if "StudentID" in c or "studentID" in c]
    overview_rows.append({
        "表名": name,
        "记录数": len(df),
        "字段数": df.shape[1],
        "学生ID字段": ", ".join(id_cols) if id_cols else "-",
        "缺失单元格占比": f"{df.isna().sum().sum() / max(df.size, 1):.2%}",
    })

overview = pd.DataFrame(overview_rows)
display(overview)

数据审计结果如下:

表名 记录数 字段数 学生ID字段 缺失单元格占比
teacher 3,088 8 - 0.00%
student 1,765 14 bf_StudentID 16.43%
attendance 23,630 10 bf_studentID 0.40%
attendance_type 15 4 - 0.00%
score 471,686 13 mes_StudentID 11.44%
exam_type 21 2 - 0.00%
consumption 463,904 5 bf_StudentID 0.00%

从审计结果可见,成绩表、消费表数据量最大,是学生学情与行为分析的核心依据。同时发现核心问题:各数据表学生ID字段命名不统一,存在 bf_StudentIDmes_StudentIDbf_studentID多种格式,后续必须统一字段名称,实现数据跨表关联。
在这里插入图片描述

五、多源数据清洗与标准化处理

本次数据清洗核心目标并非简单删除缺失值,而是将各类流水数据、异构数据统一聚合至学生单一粒度,规范字段格式、剔除异常数据,为特征工程提供标准化数据集。

5.1 学生基础信息清洗

保留学生性别、班级、住宿等核心属性,剔除冗余隐私字段,统一学生ID格式,去重去空,保证学生主表数据唯一有效。

students = tables["student"].copy()
# 统一学生ID字段格式
students["student_id"] = pd.to_numeric(students["bf_StudentID"], errors="coerce").astype("Int64")

# 去重、去空,重命名字段
students = (
    students.dropna(subset=["student_id"])
    .drop_duplicates("student_id")
    .rename(columns={
        "bf_sex": "gender",
        "cla_Name": "class_name",
        "Bf_ResidenceType": "residence_type",
        "bf_zhusu": "is_boarding",
        "bf_qinshihao": "dorm_room",
    })
)

# 筛选核心字段
base_cols = ["student_id", "gender", "class_name", "residence_type", "is_boarding", "dorm_room"]
students = students[base_cols]

5.2 学业成绩数据清洗

剔除缺考、负分等无效成绩记录,由于不同考试难度、满分标准不同,不直接对比原始分数,通过同考试、同学科百分位换算,客观反映学生相对学业水平。

scores = tables["score"].copy()
# 字段格式标准化
scores["student_id"] = pd.to_numeric(scores["mes_StudentID"], errors="coerce").astype("Int64")
scores["exam_date"] = pd.to_datetime(scores["exam_sdate"], errors="coerce")
scores["mes_Score"] = pd.to_numeric(scores["mes_Score"], errors="coerce")

# 剔除空值、异常分数
scores = scores.dropna(subset=["student_id", "mes_sub_name", "mes_Score"])
scores = scores[(scores["mes_Score"] >= 0) & (scores["mes_Score"] <= 150)].copy()

# 计算学科成绩百分位,衡量相对水平
scores["score_percentile"] = (
    scores.groupby(["exam_number", "mes_sub_name"])["mes_Score"]
    .rank(method="average", pct=True) * 100
)

5.3 校园考勤数据清洗

对原始考勤事件进行分类归纳,将零散的考勤记录划分为迟到晚到、早退、请假、缺勤、其他异常五大类,量化学生出勤行为状态。

att = tables["attendance"].copy()
att["student_id"] = pd.to_numeric(att["bf_studentID"], errors="coerce").astype("Int64")
att["event_time"] = pd.to_datetime(att["DataDateTime"], errors="coerce")
att["event_date"] = att["event_time"].dt.date
att["event_text"] = att["controler_name"].fillna("").astype(str)
att = att.dropna(subset=["student_id"])

# 考勤事件分类
att["event_group"] = np.select(
    [
        att["event_text"].str.contains("迟到|晚到", regex=True),
        att["event_text"].str.contains("早退", regex=True),
        att["event_text"].str.contains("请假|病假|事假", regex=True),
        att["event_text"].str.contains("缺勤|旷课", regex=True),
    ],
    ["迟到晚到", "早退", "请假", "缺勤"],
    default="其他考勤异常"
)

5.4 校园消费数据清洗

矫正消费金额正负值,剔除极端异常消费数据,划分消费时段,挖掘学生校园生活作息规律与活跃度特征。

cons = tables["consumption"].copy()
cons["student_id"] = pd.to_numeric(cons["bf_StudentID"], errors="coerce").astype("Int64")
cons["deal_time"] = pd.to_datetime(cons["DealTime"], errors="coerce")
cons["deal_date"] = cons["deal_time"].dt.date
cons["hour"] = cons["deal_time"].dt.hour

# 矫正消费金额,统一为正向支出
cons["spend"] = pd.to_numeric(cons["MonDeal"], errors="coerce")
cons["spend"] = np.where(cons["spend"] < 0, -cons["spend"], np.nan)

# 清洗无效、极端数据
cons = cons.dropna(subset=["student_id", "spend", "deal_time"])
cons = cons[(cons["spend"] > 0) & (cons["spend"] <= cons["spend"].quantile(0.995))].copy()

# 划分消费时段,分析生活节奏
cons["meal_period"] = pd.cut(
    cons["hour"],
    bins=[0, 9, 14, 20, 24],
    labels=["早餐/上午", "午餐/下午", "晚餐/晚间", "夜间"],
    right=False,
)

数据清洗后各维度有效数据统计如下:

数据对象 清洗后记录数 覆盖学生数
学生基础信息 1,765 1,765
有效成绩记录 403,559 3,862
考勤异常记录 23,630 3,058
消费支出记录 461,587 1,729

六、多维学生画像指标体系构建

本次实验搭建7大类可解释学情指标,覆盖学业水平、学习稳定性、出勤状态、生活规律、校园活跃度、学科均衡度、帮扶需求七大维度,所有指标统一归一化至0-100分,实现量化对比。

指标名称 计算逻辑 指标含义
学业表现指数 成绩百分位均值分位归一化 量化学生整体学业水平
学业稳定指数 成绩波动反向归一化,波动越小分数越高 衡量学生学习输出的稳定性
考勤健康指数 考勤异常次数反向归一化,异常越少分数越高 评价学生出勤行为规范性
消费规律指数 日消费变异系数反向归一化 反映学生校园生活作息规律程度
校园活跃指数 有效消费天数正向归一化 表征学生校园参与活跃度
学科均衡指数 学科分差反向归一化,差距越小分数越高 判断学生是否存在明显学科短板
支持需求指数 综合学业水平与学科短板加权计算 量化学生学情帮扶、干预需求等级

6.1 通用百分位指数工具函数

统一所有指标的归一化规则,适配正向、反向两类指标计算场景。

def percentile_index(s: pd.Series, higher_is_better: bool = True) -> pd.Series:
    """
    0-100分百分位归一化
    :param s: 待归一化序列
    :param higher_is_better: 是否为正向指标
    :return: 归一化后指数
    """
    s = pd.to_numeric(s, errors="coerce")
    filled = s.fillna(s.median())
    pct = filled.rank(pct=True, method="average") * 100
    return pct if higher_is_better else 100 - pct

6.2 学业特征聚合计算

聚合学生考试频次、成绩稳定性、学科强弱项等核心学业特征,精准定位学生优势与短板学科。

# 聚合学业基础特征
score_features = scores.groupby("student_id").agg(
    score_records=("score_percentile", "size"),
    exam_rounds=("exam_number", "nunique"),
    subject_count=("mes_sub_name", "nunique"),
    avg_score_percentile=("score_percentile", "mean"),
    score_volatility=("score_percentile", "std"),
    latest_exam_date=("exam_date", "max"),
).reset_index()

# 挖掘强弱学科
subject_matrix = scores.pivot_table(
    index="student_id",
    columns="mes_sub_name",
    values="score_percentile",
    aggfunc="mean",
)

subject_stats = pd.DataFrame({
    "student_id": subject_matrix.index,
    "strong_subject": subject_matrix.idxmax(axis=1),
    "weak_subject": subject_matrix.idxmin(axis=1),
    "subject_gap": subject_matrix.max(axis=1) - subject_matrix.min(axis=1),
}).reset_index(drop=True)

6.3 考勤与消费特征聚合

统计学生各类考勤异常频次、消费频次、日均消费、消费波动系数,量化行为与生活状态。

# 考勤特征聚合
att_basic = att.groupby("student_id").agg(
    attendance_events=("kaoqing_id", "count"),
    attendance_event_days=("event_date", "nunique"),
).reset_index()

att_pivot = (
    att.pivot_table(index="student_id", columns="event_group", values="kaoqing_id", aggfunc="count", fill_value=0)
    .reset_index()
)

att_features = att_basic.merge(att_pivot, on="student_id", how="left")

# 消费特征聚合
daily_spend = cons.groupby(["student_id", "deal_date"])["spend"].sum().reset_index()

spend_day_features = daily_spend.groupby("student_id").agg(
    active_consume_days=("deal_date", "nunique"),
    avg_daily_spend=("spend", "mean"),
    daily_spend_std=("spend", "std"),
).reset_index()

spend_basic = cons.groupby("student_id").agg(
    consume_transactions=("spend", "size"),
    total_spend=("spend", "sum"),
    avg_ticket=("spend", "mean"),
).reset_index()

consume_features = spend_basic.merge(spend_day_features, on="student_id", how="left")
consume_features["daily_spend_cv"] = (
    consume_features["daily_spend_std"] / consume_features["avg_daily_spend"].replace(0, np.nan)
)

6.4 画像宽表合并与指数计算

整合所有维度特征,填充空值,加权计算综合成长指数与帮扶需求指数,完成学生量化画像构建。

# 合并全维度特征
profile = (
    students
    .merge(score_features, on="student_id", how="left")
    .merge(subject_stats, on="student_id", how="left")
    .merge(att_features, on="student_id", how="left")
    .merge(consume_features, on="student_id", how="left")
)

# 计数类空值填充为0
count_cols = [
    "score_records", "exam_rounds", "subject_count",
    "attendance_events", "attendance_event_days",
    "consume_transactions", "active_consume_days",
    "迟到晚到", "早退", "请假", "缺勤", "其他考勤异常"
]

for col in count_cols:
    if col in profile.columns:
        profile[col] = profile[col].fillna(0)

# 计算0-100标准化指数
profile["academic_index"] = percentile_index(profile["avg_score_percentile"], True)
profile["academic_stability_index"] = percentile_index(profile["score_volatility"], False)
profile["attendance_health_index"] = percentile_index(profile["attendance_events"], False)
profile["consumption_regular_index"] = percentile_index(profile["daily_spend_cv"], False)
profile["campus_activity_index"] = percentile_index(profile["active_consume_days"], True)
profile["subject_balance_index"] = percentile_index(profile["subject_gap"], False)

# 加权计算综合成长指数
profile["overall_growth_index"] = (
    0.34 * profile["academic_index"]
    + 0.18 * profile["academic_stability_index"]
    + 0.18 * profile["attendance_health_index"]
    + 0.12 * profile["consumption_regular_index"]
    + 0.10 * profile["campus_activity_index"]
    + 0.08 * profile["subject_balance_index"]
)

# 计算帮扶需求指数
gap_pressure = percentile_index(profile["subject_gap"], True)
profile["support_need_index"] = (100 - profile["overall_growth_index"]) * 0.78 + gap_pressure * 0.22
profile["support_need_index"] = profile["support_need_index"].clip(0, 100)

6.5 量化指数转语义标签

将连续型量化指数转化为可直观解读的学情标签,构建规则画像基线,适配人工理解与初步筛选场景。

# 学习层级标签
profile["learning_level"] = pd.cut(
    profile["academic_index"],
    bins=[-1, 35, 70, 100],
    labels=["基础巩固型", "稳步发展型", "优势拓展型"],
)

# 帮扶需求标签
profile["support_segment"] = pd.cut(
    profile["support_need_index"],
    bins=[-1, 35, 65, 100],
    labels=["低支持需求", "中支持需求", "高支持需求"],
)

# 考勤状态标签
profile["attendance_style"] = pd.cut(
    profile["attendance_health_index"],
    bins=[-1, 40, 75, 100],
    labels=["考勤需关注", "考勤基本稳定", "考勤稳定"],
)

# 生活节奏标签
profile["consumption_style"] = pd.cut(
    profile["consumption_regular_index"],
    bins=[-1, 40, 75, 100],
    labels=["消费节奏波动", "消费节奏一般", "消费节奏规律"],
)

# 筛选有效画像数据
profile_ready = profile.dropna(subset=["academic_index"]).copy()

最终完成1765名学生的全维度画像构建,样本综合成长指数均值为50.00,帮扶需求指数均值为50.01,整体学情分布均衡。

七、学生画像结果可视化与分析

为直观呈现学生学情分布特征,对学业表现、考勤健康、消费规律、帮扶需求四大核心指数进行可视化分析,并完成数据相关性、学科短板分布研究。

7.1 核心指数分布可视化

通过直方图展示各指数整体分布规律,辅助判断整体学情特征。

fig, axes = plt.subplots(2, 2, figsize=(12, 8))

plot_specs = [
    ("academic_index", "学业表现指数"),
    ("attendance_health_index", "考勤健康指数"),
    ("consumption_regular_index", "消费规律指数"),
    ("support_need_index", "支持需求指数"),
]

colors = ["#2E6F95", "#8AB17D", "#E9C46A", "#E76F51"]

for ax, (col, title), color in zip(axes.ravel(), plot_specs, colors):
    ax.hist(profile_ready[col].dropna(), bins=24, color=color, edgecolor="white", alpha=0.9)
    ax.axvline(profile_ready[col].median(), color="#333333", linestyle="--", linewidth=1)
    ax.set_title(title)
    ax.set_xlabel("指数值")
    ax.set_ylabel("学生数")

fig.suptitle("学生画像核心指数分布", fontsize=15)
fig.tight_layout()
fig.savefig(OUTPUT_DIR / "02_profile_index_distribution.png", dpi=180, bbox_inches="tight")
plt.show()

7.2 学生学情分层统计

结合学习层级与帮扶需求完成学生分层,统计结果显示,全校17.5%的学生属于高帮扶需求群体,该部分学生普遍存在学业薄弱、学科短板突出、行为作息不规律等多重问题,是教学干预的重点对象。

7.3 指标相关性分析

通过相关性热力图可见,综合成长指数与帮扶需求指数呈显著负相关,符合指标设计逻辑;学业、考勤、生活各维度指标相关性较弱,证明多维画像可从不同角度刻画学生状态,相比单一成绩评价更全面。

7.4 薄弱学科分布统计

统计结果显示,艺术类学科为多数学生的薄弱项,该结果并非核心学业问题,提示后续资源推荐需结合学科属性过滤非核心学科,保证推荐针对性。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

八、传统规则画像基线构建

基于量化标签拼接生成结构化规则画像,形成传统学情分析基线模型,该方法优势为完全可解释、稳定性高,可快速批量生成学生学情标签。

def build_rule_profile(row: pd.Series) -> str:
    """拼接学生规则画像标签"""
    parts = [
        f"{row['learning_level']}",
        f"{row['support_segment']}",
        f"{row['attendance_style']}",
        f"{row['consumption_style']}",
    ]
    if pd.notna(row.get("weak_subject")):
        parts.append(f"薄弱学科:{row['weak_subject']}")
    if pd.notna(row.get("strong_subject")):
        parts.append(f"优势学科:{row['strong_subject']}")
    return " | ".join(map(str, parts))

profile_ready["rule_profile"] = profile_ready.apply(build_rule_profile, axis=1)

抽取三名典型学生完成画像对比,可清晰区分优等生、中等生、学困生的多维差异,但规则画像表述机械、缺乏个性化解读,无法输出可落地的学习建议,这是后续引入大模型的核心原因。

九、基于千问大模型的智能画像生成

为弥补规则画像的局限性,本次实验调用千问大语言模型,将匿名化的学生结构化指标转化为自然语言学情诊断报告,实现智能化、个性化的学情解读。全程仅传入聚合指标,不涉及学生隐私数据,保证数据安全。

9.1 构建模型输入数据

筛选核心学情指标,精简数据维度,生成标准化模型输入载荷。

def compact_student_record(row: pd.Series) -> dict:
    """生成精简匿名学生指标数据"""
    keys = [
        "student_id", "gender", "class_name", "learning_level", "support_segment",
        "attendance_style", "consumption_style", "strong_subject", "weak_subject",
        "academic_index", "academic_stability_index", "attendance_health_index",
        "consumption_regular_index", "campus_activity_index", "subject_balance_index",
        "overall_growth_index", "support_need_index", "score_records", "attendance_events",
        "consume_transactions",
    ]
    record = {}
    for key in keys:
        value = row.get(key)
        if isinstance(value, (np.integer, np.floating)):
            value = float(value)
        if isinstance(value, float):
            value = round(value, 2)
        if pd.isna(value):
            value = None
        record[key] = value
    return record

9.2 千问模型接口调用

基于OpenAI兼容接口调用千问模型,设置固定输出格式,保证结果结构化、可复用。

from openai import OpenAI

def call_qwen_json(messages, fallback: dict, model: str = "qwen-turbo") -> tuple[dict, bool, str]:
    """调用千问模型,返回结构化JSON结果"""
    api_key = os.getenv("DASHSCOPE_API_KEY")
    if not api_key:
        return fallback, False, "未检测到 DASHSCOPE_API_KEY,使用本地兜底结果"

    try:
        client = OpenAI(
            api_key=api_key,
            base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
        )
        completion = client.chat.completions.create(
            model=model,
            messages=messages,
            temperature=0.2,
            response_format={"type": "json_object"},
        )
        content = completion.choices[0].message.content
        return json.loads(content), True, f"模型调用成功:{model}"
    except Exception as exc:
        return fallback, False, f"模型调用失败,使用本地兜底结果:{type(exc).__name__}: {exc}"

9.3 提示词设计与画像生成

通过精准系统提示词约束模型输出,禁止编造隐私信息,规范输出字段,生成包含画像标题、学习状态、风险成因、干预优先级、提升策略的完整智能画像。

模型输出结果可精准匹配学生多维学情,将冰冷的量化指标转化为通俗易懂、贴合教学场景的学情诊断,极大提升了画像的实用性。
在这里插入图片描述
在这里插入图片描述

十、传统规则推荐基线搭建

在智能推荐前,搭建传统规则推荐基线,基于学生薄弱学科、帮扶需求等级生成通用学习建议,作为后续智能推荐的对比基准。该方法简单高效,但仅能实现粗略的方向指导,无法匹配具体学习资源。

十一、教育资源库构建与向量库入库

为实现精准资源匹配,自建覆盖全学科的教育资源库,包含基础巩固、能力提升、学习习惯培养三类资源,共计16条优质学习资源。随后依托Chroma向量数据库,将资源文本向量化,搭建语义检索引擎。

通过开源轻量嵌入模型完成文本向量化,以余弦相似度为检索依据,将向量库持久化存储,保证检索效率与稳定性。

import chromadb
from chromadb.utils.embedding_functions.onnx_mini_lm_l6_v2 import ONNXMiniLM_L6_V2

# 配置模型缓存路径
chroma_cache = F_ENV_ROOT / "chroma_cache" / "onnx_models" / ONNXMiniLM_L6_V2.MODEL_NAME
ONNXMiniLM_L6_V2.DOWNLOAD_PATH = chroma_cache

# 向量库存储路径
chroma_db_path = OUTPUT_DIR / "chroma_resource_db"
chroma_db_path.mkdir(parents=True, exist_ok=True)

# 初始化嵌入模型与向量客户端
embedding_fn = ONNXMiniLM_L6_V2()
chroma_client = chromadb.PersistentClient(path=str(chroma_db_path))

# 新建资源集合
collection_name = "edu_resource_bank_original_v1"
try:
    chroma_client.delete_collection(collection_name)
except Exception:
    pass

collection = chroma_client.create_collection(
    name=collection_name,
    embedding_function=embedding_fn,
    metadata={"hnsw:space": "cosine"},
)

# 资源入库
collection.add(
    ids=resource_df["id"].tolist(),
    documents=resource_df["document"].tolist(),
    metadatas=resource_df[["subject", "difficulty", "title", "tags"]].to_dict(orient="records"),
)

print("资源入库数量:", collection.count())

十二、基于学生画像的语义资源检索

整合学生智能画像文本,构建个性化检索问句,结合语义相似度+学科匹配度双重权重,对召回资源进行精准排序,兼顾语义适配性与学情针对性。

检索结果不仅精准匹配学生薄弱学科资源,还可根据学生生活作息问题,召回学习习惯、生活节奏管理类通用资源,突破传统单一学科匹配的局限。

十三、大模型个性化推荐报告生成

将学生画像数据、TOP5候选资源传入千问模型,通过提示词严格约束:仅基于现有候选资源生成内容,禁止虚构资源、脱离学情推荐。最终模型输出包含学情诊断、三周可执行学习计划、精准资源推荐、使用注意事项的完整个性化报告。

生成的推荐方案落地性极强,既针对性补强学生学科短板,又兼顾学习习惯、生活作息优化,实现全方位学情帮扶。

十四、多方法技术对比分析

本次实验融合四种学情分析与推荐方法,各技术分工明确、互补增效,不存在相互替代关系,具体对比如下:

技术方法 核心优势 存在短板 实验定位
规则画像建模 透明可解释、运行稳定、零成本 表达机械,无法综合解读复杂学情 构建基线画像,为模型提供标准化输入
传统规则推荐 逻辑简单、落地便捷、适合快速预警 资源匹配粗糙,无语义适配能力 搭建推荐基线,用于效果对比
向量语义检索 支持语义匹配,适配复杂学情需求 依赖资源库质量与嵌入模型效果 负责精准资源召回,筛选候选资源
LLM智能生成 解释性强、可生成落地计划、个性化程度高 需要严格提示词约束,存在输出不确定性 负责学情解读与个性化报告生成

十五、实验核心结论

1. 学生智能画像构建必须先量化、后智能。依托多源数据清洗与指标工程生成结构化特征,是大模型精准解读学情的核心基础,直接投喂原始数据会导致结果失真、不可控。

2. 向量检索技术可有效解决传统推荐语义缺失的问题,能够根据学生综合学情,跨场景匹配学科补强、习惯培养类资源,提升推荐全面性。

3. 大语言模型的核心价值在于内容解释与方案生成,而非数据计算。结合结构化指标与

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐