技术向 / 干货。面向想用「系统」替代「纯人工盯娃记录」的家长与开发者。 作者:学心教研

「孩子学习状态不好怎么调整」是个伪问题——真问题是家长根本没时间、也没有稳定口径去观察孩子每天到底发生了什么。低年级还能翻翻作业本,初中以后孩子放学就关门,家长看到的是"状态不好"四个字,但说不出是哪一天、哪件事、哪个环节掉的线。
在学科极度内卷的形势下,额外给孩子增加一个竞争优势,靠的不是再多报一门课——而是把「观察与沟通」从一件依赖家长心力的手工活,变成一条能稳定跑起来的自动化流水线,让机器做记录的总账,让人做判断的定盘。 本方案就是这条流水线的工程化落地:把家长与孩子每天自然的几句对话,变成后台数据库里一条条结构化记录,再自动聚合成每周面谈时能直接对账的复盘报告。
一条「AI 替代纯人工」的每日沟通流水线,至少要拆成四个可独立实现的环节:
环节 | 纯人工的痛点 | 工程目标 |
|---|---|---|
① 沟通入口 | 家长不知道每天问什么、孩子也不愿意说 | 在手机 App/小程序里,用"低门槛聊天"承接每日变化、遇到的问题、任务打卡 |
② 回复机制 | 家长不会回,容易说教,沟通越走越僵 | 让孩子看见"被看见、被鼓励",AI 按咨询师口径给正向回复 |
③ 数据记录 | 聊完就忘,一星期后只剩模糊印象 | 聊天时顺手把状态结构化落库,作为周/月复盘的原始凭证 |
④ 复盘应用 | 每周面谈要现翻记忆、漏事 | 由数据库自动聚合本周概况,面谈时直接对账 |
四个点串起来是一条闭环流水线:采集(①) → 生成(②) → 存储(③) → 复盘(④)。下面按流水线的顺序讲,每一环给出能落地的代码。
孩子抵触的是"被审问",不抵触"打卡 + 被关心"。所以入口设计成两种:
无论哪个入口,最终都收敛成一条"事件记录",字段刻意保持少而稳:
# event.py —— 每日事件的最小结构化模型
from dataclasses import dataclass, field
from datetime import date
from enum import Enum
from typing import Optional
class Tracker(str, Enum): # 学心四力的观测代理
DIRECTING = "心航力" # 方向:今天知不知道自己该做什么
FOCUS = "心定力" # 专注:在不在任务上
RESILIENCE = "心韧力" # 抗挫:卡住之后能不能回来
EFFICACY = "心效力" # 胜任:信不信自己能做成
@dataclass
class Event:
child_id: str # 归到哪个孩子
day: date # 发生日期(对账的主键之一)
kind: str # "checkin" 打卡 / "qa" 问答
tracker: Tracker # 本事件主要落在哪个力上
ok: Optional[bool] # 打卡类:完成了没
blocker: Optional[str] # 打卡类:卡在哪
raw_text: str # 问答类:孩子的原话(脱敏后入库)
sentiment: float = 0.0 # AI 打的情感分,-1~1,落库用
created_at: str = field(default_factory=lambda: __import__("datetime").datetime.now().isoformat())设计要点:一个事件只归一个力(宁可粗,不能乱)。多目标任务的白名单不如"一天只归一类",这正是 W37 复盘里"按状态调、不按题型刷"在数据层的体现。
通用大模型一上来容易"说教三连"(你应该/你必须/你不能),正是家长沟通最忌讳的。方案是把咨询师的接话范式和针对这个孩子的事实两样东西,喂给一个受控的生成器:
# reply.py —— 决定"怎么说",而不是让模型自由发挥
SYSTEM_RULE = (
"你是一名温和的儿童心理陪伴助手。接到孩子的反馈时:"
"1) 先共情,复述他描述的具体事实;"
"2) 用一句话把行为翻译成可训练的能力(方向/专注/抗挫/胜任);"
"3) 给出一个'明天可以试一试'的具体小动作;"
"4) 字数≤60,绝不批评,绝不贴标签。"
)
def build_prompt(event: Event, child_profile: str) -> str:
# 知识库注入:孩子的历史趋势 + 四力口径,让 AI 的接话"有上下文"
trend = summarize_history(event.child_id, event.day) # 见关③
return f"【孩子档案】{child_profile}\n【近期趋势】{trend}\n" \
f"【本次输入】{event.raw_text or event.blocker or '今日打卡完成'}\n" \
f"依据 {SYSTEM_RULE} 给出回复。"SYSTEM_RULE 这段不是可有可无的提示词美化,它是安全与口径的硬护栏:保证所有每日回复都落在"共情→能力翻译→小动作"三拍内,避免 AI 越过咨询师角色去给诊断或承诺结果。这也是为什么它必须在系统层写死、不允许末位覆盖。
每条对话事件异步写入后台数据库(本示例用 SQLite,生产可换 PostgreSQL),并在同一事务里聚合出"当日一行"指标:
# store.py —— 落库 + 每日聚合成一张"对账表"
import sqlite3, datetime
SCHEMA = """
CREATE TABLE IF NOT EXISTS events(
child_id TEXT, day TEXT, kind TEXT, tracker TEXT, ok INTEGER,
blocker TEXT, raw_text TEXT, sentiment REAL, created_at TEXT
);
CREATE TABLE IF NOT EXISTS daily_metrics(
child_id TEXT, day TEXT PRIMARY KEY,
n_directing INTEGER DEFAULT 0, n_focus INTEGER DEFAULT 0,
n_resilience INTEGER DEFAULT 0, n_efficacy INTEGER DEFAULT 0,
ok_rate REAL, avg_sentiment REAL
);
"""
def upsert_today(conn, child_id: str, day: str = str(datetime.date.today())):
"""每次写入后,把当日记录收敛成一行,供周复盘直接取用。"""
row = conn.execute(
"SELECT COUNT(*), COALESCE(AVG(ok),0), COALESCE(AVG(sentiment),0) "
"FROM events WHERE child_id=? AND day=? AND ok IS NOT NULL", (child_id, day)
).fetchone()
n_ok, ok_rate, avg_senti = row[0], (row[1] or 0), (row[2] or 0)
counts = {t: 0 for t in ("心航力", "心定力", "心韧力", "心效力")}
for t, c in conn.execute(
"SELECT tracker, COUNT(*) FROM events WHERE child_id=? AND day=? GROUP BY tracker",
(child_id, day)):
counts[t] = c
conn.execute(
"INSERT OR REPLACE INTO daily_metrics(child_id, day, n_directing, n_focus, "
"n_resilience, n_efficacy, ok_rate, avg_sentiment) "
"VALUES(?,?,?,?,?,?,?,?)",
(child_id, day, counts["心航力"], counts["心定力"], counts["心韧力"],
counts["心效力"], ok_rate, avg_senti))
conn.commit()复盘的原则是不追分、只追趋势:单日数据噪声极大,真正有用的是"哪条曲线先拐头"。所以存储层不做"今天达标没",只做逐日一行,把"曲线形状"留给复盘环节判断。
每周家长与孩子在线面谈一次,面谈前由 pipeline 生成一份"本周复盘":7 日的逐日指标 + 每条力曲线的 5 日滑动均值 + 本周出现过的"卡点原话",让面谈直奔主题、不说废话。
# weekly.py —— 每周复盘报告
def weekly_report(conn, child_id: str, day: str):
since = (datetime.date.fromisoformat(day) - datetime.timedelta(days=6)).isoformat()
rows = conn.execute(
"SELECT day, n_resilience, n_focus, n_directing, n_efficacy, "
"ROUND(ok_rate,2), ROUND(avg_sentiment,2) "
"FROM daily_metrics WHERE child_id=? AND day>=? ORDER BY day", (child_id, since)
).fetchall()
# 关键卡点:把孩子的原话问题也一起带进面谈
blockers = [r[0] for r in conn.execute(
"SELECT blocker FROM events WHERE child_id=? AND day>=? AND blocker IS NOT NULL "
"ORDER BY created_at", (child_id, since)).fetchall() if r[0]]
return {"days": rows,
"curve": moving_avg([r[1] for r in rows], window=5), # 抗挫力是复盘主盯项
"blockers": blockers}需要反复强调一条边界:这份报告是给面谈用的材料,不是给家长的断言。当数据与家长直觉冲突时,以实际观察为准——AI 的作用是防遗忘、防误归因,把每周面谈从"靠记忆翻旧账"变成"对着 7 天总账逐条对"。数据负责"记得全",人负责"怎么调"。
环节 | 纯人工 | 本流水线 |
|---|---|---|
采集入口 | 靠家长想起来问,依赖当天状态 | 打卡+问答双通道,弱约束持续采集 |
回复 | 家长凭情绪回,容易说教 | 咨询师口径受控生成,稳定三拍 |
记录 | 聊完即忘,周复盘靠翻记忆 | 对话即结构化落库,零额外录入 |
复盘 | 面谈前临时翻,漏事、凭印象 | 逐日一行自动聚合,直接对账 |
成本结构:单条事件落库是亚毫秒级异步写;周报告是 7 行数据的聚合,一次性跑完 <10ms。整条流水线纯 CPU 就能扛住日活万级的每日采集量,真正稀缺的资源从"机器算力"转移到"家长的判断力"。
avg_sentiment 只用于看趋势拐点,绝不用于给孩子贴"心理状态差"的标签;它和四力曲线一样,是"先看哪条拐头"的线索。raw_text 入库前要走脱敏(人名/学校/成绩);复盘只取聚合值与卡点,不取全文。Q:每天十分钟就够?对话多了孩子不烦吗?
A:够。设计原则是"低门槛":打卡一次 ≤10 秒,问答想聊就聊、不想聊不强求。它的价值不在对话量,而在每天都有一次稳定触点——正是"每日短时高频 > 每周一次长谈"在数据层的体现。
Q:这套东西会不会让 AI 越界替我做教育决定?
A:不会,边界写死在系统层:AI 只负责"共情表述 + 能力翻译 + 记录、聚合",所有"明天怎么调"的决定权保留给家长与孩子。若数据与直觉冲突,以你的实际观察为准。
Q:用什么技术栈能最小跑起来?
A:上面示例是纯 Python + SQLite,前端一个最简单的 H5/小程序即可承载打卡与问答两个入口。先把"每日一行落库 + 周报告聚合"跑通,再谈引入向量检索做知识库扩展。建议先扫一遍历史错题与近两周状态做口径校准(详见相关阅读)。
学心四力(心理能量四维 + 家庭土壤)—— 解决的是孩子「撑得住撑不住」的持久问题,不是「学得快不快」。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。