
学习场景里一直有一个很现实的矛盾学生在遇到难题时既希望马上得到答案又担心只是“抄了个答案”而没真正学会。而传统教育软件通常只有两种极端——要么是静态题库要么是直接给解析文本。随着大语言模型LLM的能力逐渐成熟越来越多团队开始尝试用 AI 做“启发式教学”不让它直接告诉你结果而是像老师一样不断提问、引导、纠正思路。今天要聊的DeepTutor正是这一方向上一个值得关注的开源项目它由 HKUDS 实验室香港大学数据科学实验室提出聚焦于“深度思考型 AI 辅导系统”。本文将围绕 DeepTutor 展开先讲清楚它是什么、要解决什么问题再拆解其核心设计思路然后给出一个可运行的实战案例最后补充部署、评测和工程化落地时容易踩的坑。无论你是做教育产品的后端工程师还是对大模型智能体Agent感兴趣的算法工程师这篇文章都能提供一个相对完整的参考。1. DeepTutor 是什么一个面向深度学习的 AI 辅导智能体1.1 HKUDS 与 DeepTutor 的背景HKUDS 是香港大学数据科学实验室的简称主要研究方向包括大语言模型、数据挖掘、智能体系统等。实验室曾开源过多个在大模型应用层有一定影响力的项目。DeepTutor 是其中比较有代表性的一个教育场景项目它的定位很简单用大语言模型构建一个“会追问、会启发、会纠错”的 AI 导师。传统的在线教育系统里AI 助教最常见的能力是“学生提问AI 直接给答案”。这种模式对信息检索效率有帮助但对学习效果帮助有限。因为真正的学习过程需要学生主动思考、试错、反思。DeepTutor 的设计目标不是做一个“答案生成器”而是做一个“思维引导器”它更关注学生是怎么想的而不是学生要什么结论。1.2 DeepTutor 要解决的核心问题我们可以把 DeepTutor 要解决的问题拆成三个层面第一层如何不让 AI 直接泄露答案。大模型默认行为是“尽量满足用户指令”学生问“这道题怎么解”模型往往会把完整解题过程写出来。DeepTutor 需要通过提示词和策略约束模型的输出行为让它先问学生“你目前是怎么想的”“你卡在哪一步”再逐步引导。第二层如何识别学生的错误思路。学生给出的回答往往是含糊的甚至带有错误假设。AI 导师需要从学生的话里抽取关键状态判断他是在概念理解上出问题还是在计算过程上出问题然后针对性地反馈。第三层如何做到多轮引导而不是一次性灌输。教学不是单轮问答。学生可能在一个问题上需要来回讨论七八轮。DeepTutor 需要在每一轮都能基于对话历史调整策略既要记录学生已经掌握的部分也要记住哪些点还没讲透。1.3 与普通 AI 助手的区别有的同学可能会问这跟普通 ChatGPT 有什么区别我完全可以自己写一段提示词“不要直接告诉我答案请引导我思考。”区别在于提示词只是单点策略而 DeepTutor 是一套完整的对话状态管理方案。单靠提示词能约束模型“今天别给答案”但无法可靠地处理以下问题如果学生连续答错什么时候应该降低难度如果学生表现出明显挫败感要不要先给一点提示如何判断学生是真的理解了还是只是重复了 AI 刚才说过的话如何把一次辅导过程沉淀成结构化的学习记录这些都需要在系统层面做设计而不是靠一两句 prompt 就能解决。DeepTutor 的意义在于把“启发式教学”从一个灵感变成了一套可实现的工程方案包括教学策略、对话管理、状态追踪和评估反馈等模块。2. 环境准备与项目部署思路2.1 建议的运行环境在真正动手运行 DeepTutor 或同类项目之前我们需要先把环境准备好。由于 DeepTutor 是基于大模型 API 的智能体应用它本身对硬件要求不高核心依赖是 Python 环境和一个可用的 LLM API。建议环境如下项目建议配置说明操作系统Linux / macOS / WindowsWSL2推荐 Linux 服务器部署更稳定Python3.9 及以上大部分 LLM 项目已适配新版本模型服务OpenAI 兼容 API 或本地部署模型需确认服务地址和密钥依赖管理pip venv / conda避免污染全局环境代码仓库Git用于克隆项目源码版本需要根据你的项目实际情况调整本文示例以常见环境为例重点演示配置思路。如果你的机器支持 CUDA 且显存足够也可以考虑本地部署量化模型来替代远程 API但这样会增加部署复杂度建议新手先从 API 模式开始。2.2 获取与部署开源项目DeepTutor 以开源项目的形式发布通常托管在 GitHub 上。获取代码的通用方式如下git clone https://github.com/HKUDS/DeepTutor.git cd DeepTutor进入项目目录后一般需要创建虚拟环境并安装依赖python -m venv venv source venv/bin/activate # Windows 下执行 venv\Scripts\activate pip install -r requirements.txt这里需要提醒的是不同项目的依赖文件命名可能不同常见的有requirements.txt和pyproject.toml。如果你看到的是pyproject.toml可以通过pip install -e .来安装项目本身及其依赖。2.3 模型服务与密钥配置大模型应用几乎都需要配置 API 密钥。无论 DeepTutor 内部封装得多好最终都需要调用某个 LLM 服务。常见的配置方式是在项目根目录创建.env文件# 通用配置模板具体字段以项目 README 为准 LLM_API_KEYyour-api-key LLM_BASE_URLhttps://api.example.com/v1 LLM_MODELyour-model-name配置完成后可以通过环境变量加载工具读取。例如 Python 中常用的python-dotenvfrom dotenv import load_dotenv import os load_dotenv() api_key os.getenv(LLM_API_KEY) base_url os.getenv(LLM_BASE_URL) model os.getenv(LLM_MODEL)一个常见的错误是直接把 API 密钥硬编码在代码里然后提交到 Git 仓库。这会导致密钥泄露轻则产生额外费用重则影响账号安全。正确做法是使用.env文件并在.gitignore中把它忽略掉。3. 核心原理拆解如何让 AI 学会“启发式教学”前面说过DeepTutor 的价值在于把教学策略工程化。下面我们逐一拆解它的核心模块。这几块内容不仅适用于 DeepTutor 本身也适用于任何想构建“AI 导师”类应用的开发者。3.1 从“给答案”到“引导思考”教学策略提示词要让大模型不直接给答案最基础的手段是提示词设计。但这里的提示词并不是简单写一句“别告诉我答案”而是要给模型一套可执行的规则。一个典型的“引导式教学”提示词可能长这样你是一名耐心的高中数学老师。你的目标不是帮学生直接解出题目而是通过提问和提示引导学生自己找到解题思路。 规则 1. 当学生问你题目时先不要给出答案也不要展示完整解题过程。 2. 先询问学生对这道题的理解“你读完题后觉得题目在考察什么知识点” 3. 根据学生的回答判断他的基础水平再决定下一步引导的深度。 4. 如果学生卡住太久可以给出一个小提示但只给下一步思路不给答案。 5. 如果学生给出正确答案让他再解释一遍思路确认他是否真的理解。这里的关键点是行为约束要具体不能只给抽象指令。大模型对“启发式教学”的理解取决于训练数据如果不做规则约束它很容易退化成直接给答案。像上面第五点提到的“让学生复述思路”就是很有效的防止“假装学会”的手段。3.2 多轮对话状态管理大模型的对话接口本身是无状态的——每次调用都是一次独立推理。为了让 AI 导师记住学生上一轮说了什么需要在系统层面维护对话上下文。最简单的方式是直接把完整历史拼接到 prompt 中例如对话历史 学生这道题我不会做。 AI你觉得这道题考的是什么知识点 学生可能是二次函数吧。 当前问题请根据上面的对话决定下一步怎么引导。这种方式实现简单但存在两个问题一是 token 消耗会随对话轮次线性增长。对话越长每次请求的输入 token 就越多费用和延迟都会上升。二是上下文过长会稀释模型注意力。模型可能忘记早期的信息或者对最新指令的遵循度下降。更工程化的做法是把对话历史整理成结构化的“会话状态”只保留关键信息。例如{ student_id: stu_1001, topic: 二次函数, difficulty_level: 3, key_questions: [ { question: 求函数 y x^2 - 4x 3 的顶点坐标, student_answer: 不会, hint_given: true, status: in_progress } ], known_points: [能识别二次函数的一般形式], weak_points: [不会配方, 不确定顶点公式] }每次对话结束后从模型输出中抽取结构化信息更新这个状态对象。下一轮调用时把状态摘要和用户最新输入一起传给模型。这比单纯拼接历史更可控也更节省 token。3.3 个性化与学生画像每位学生的基础不同。同样是“二次函数”这个知识点有的学生是没记住顶点坐标公式有的是前面一元二次方程没学扎实。AI 导师如果能记录学生的知识薄弱点就可以更有针对性地出题和引导。具体实现上可以在会话状态里维护一张“知识掌握情况表”{ mastery_map: { 一元一次方程: mastered, 配方法: learning, 二次函数图像: not_started } }当学生触发某个知识点时AI 根据当前的掌握等级调整互动策略。例如mastered状态可以快速跳过learning状态需要多给提示not_started状态需要先补基础概念。这个思路跟很多人熟悉的“自适应学习系统”一脉相承只不过 DeepTutor 的做法是利用大模型来动态判定学生掌握度而不是依赖预设题库。3.4 评估与反馈闭环没有评估的教学是不完整的。DeepTutor 作为 AI 导师也需要回答一个核心问题这次辅导到底有没有效果常规做法是在辅导结束后让 AI 生成一份结构化总结{ session_score: 0.78, num_questions: 5, num_correct_first_try: 2, main_difficulty: 配方步骤不熟练, suggested_next_topics: [二次函数图像平移, 二次函数最值问题] }这份总结既可以展示给学生也可以沉淀到学习档案中供老师或系统做后续学习路径规划。评估指标不必追求复杂重点在于“是否能反映学生的真实状态变化”。如果想做更精细的评估可以引入人工标注样本对 AI 生成的总结做定期抽检。4. 实战搭建一个 DeepTutor 风格的辅导对话服务接下来我们进入实战环节。这里我不直接贴 DeepTutor 官方仓库的完整代码而是带大家手动搭建一个“DeepTutor 风格”的最小实现。这样做的目的是帮助你理解核心链路——当你回头再去看官方源码时会轻松很多。4.1 项目结构先规划一下项目文件结构tutor-demo/ ├── main.py ├── prompts.py ├── tutor_state.py ├── requirements.txt └── .env用一个简单的模块划分来模拟 DeepTutor 的关键模块prompts.py负责提示词定义tutor_state.py负责对话状态管理main.py负责主流程。4.2 定义教学角色提示词先创建prompts.pySYSTEM_PROMPT 你是一位专注于启发式教学的 AI 导师。 你的目标是帮助学生自己找到解题思路而不是直接给出答案。 教学策略 1. 当学生提问时先询问他的思考过程例如“你目前是怎么想的” 2. 当学生给出部分正确的回答时先肯定正确部分再指出不足。 3. 当你需要提示时请使用提问的方式给出“下一步思路”不要直接给完整过程。 4. 如果学生连续三次答错可以适当降低问题难度换一个更基础的例子。 5. 如果学生最终得出正确答案请他用自己的话解释一遍过程。 始终使用中文回复。 这段提示词定义了 AI 导师的基本人设和行为规则。它没有绑定具体学科可以通用于数学、物理、编程等多种学习场景。如果你希望限定在某个学科可以在提示词中追加学科要求。4.3 对话管理核心逻辑接下来创建tutor_state.pyimport json class TutorState: 保存一次辅导会话的核心状态 def __init__(self, student_id: str, topic: str): self.student_id student_id self.topic topic self.wrong_count 0 self.correct_count 0 self.history [] self.weak_points [] def add_exchange(self, student_msg: str, tutor_msg: str): self.history.append({ student: student_msg, tutor: tutor_msg }) def record_wrong(self): self.wrong_count 1 def reset_wrong_count(self): self.wrong_count 0 def to_summary(self) - str: 将状态摘要成文本供模型继续推理时使用 return json.dumps({ student_id: self.student_id, topic: self.topic, wrong_count: self.wrong_count, correct_count: self.correct_count, recent_history: self.history[-4:], weak_points: self.weak_points }, ensure_asciiFalse)这个类负责记录学生连续答错的次数用于触发降难度策略。最近几轮对话内容用于上下文拼接。已经识别出的薄弱点。这里的关键设计是不要把全量历史都传给模型保留最近几轮即可。这样既节省 token又能维持模型对对话语境的把握。4.4 主流程调用大模型实现引导式对话现在编写main.py这是整个示例的核心from openai import OpenAI from prompts import SYSTEM_PROMPT from tutor_state import TutorState def create_client(): 根据环境变量创建 OpenAI 兼容客户端 import os from dotenv import load_dotenv load_dotenv() return OpenAI( api_keyos.getenv(LLM_API_KEY), base_urlos.getenv(LLM_BASE_URL) ) def tutor_once(client, state: TutorState, student_input: str) - str: 调用大模型进行一次辅导交互。 返回 AI 导师的回复文本。 # 将系统提示词、状态摘要、学生输入拼成消息列表 messages [ {role: system, content: SYSTEM_PROMPT}, {role: system, content: f当前会话状态{state.to_summary()}}, {role: user, content: student_input} ] resp client.chat.completions.create( modelos.getenv(LLM_MODEL), messagesmessages, temperature0.4 ) return resp.choices[0].message.content if __name__ __main__: client create_client() state TutorState(student_iddemo_001, topic二次函数) print(AI 导师已就绪。输入题目开始学习输入 exit 退出。) while True: student_input input(\n学生: ) if student_input.lower() exit: break reply tutor_once(client, state, student_input) print(f\nAI 导师: {reply}) # 简单模拟这里把模型回复存进历史方便下一轮引用 state.add_exchange(student_input, reply)这里的消息组织方式值得注意我们用了两个system消息。第一个定义 AI 导师的全局人设第二个提供当前会话状态。在大部分 OpenAI 兼容接口中多个 system 消息会被合并处理这种方式可以避免把状态摘要直接拼进用户问题里语义上更清晰。4.5 运行与效果验证在项目目录下先安装依赖pip install openai python-dotenv然后确认.env文件中已经配置好LLM_API_KEY你的密钥 LLM_BASE_URL你的模型服务地址 LLM_MODEL你的模型名称运行python main.py我在这里给出一个简化但真实感很强的交互演示学生: 二次函数 y x^2 - 4x 3 的顶点坐标怎么求 AI 导师: 你之前学过配方法吗如果学过可以先试着把 x^2 - 4x 3 配成完全平方的形式。你觉得应该怎么配 学生: 是不是 x^2 - 4x 4 - 1 AI 导师: 没错你已经做对了一部分x^2 - 4x 4 可以写成 (x - 2)^2那么原来的式子应该写成什么形式还剩下什么需要处理呢你可以看到AI 导师并没有直接说出“顶点坐标是 (2, -1)”而是沿着学生的思路一步步往下引。如果学生答错state 中的wrong_count会累积达到阈值后可以在后续的 prompt 中要求模型降低难度。这就是一个最简单的“策略动态调整”雏形。4.6 给示例增加策略控制上面的代码还没有真正用到record_wrong和reset_wrong_count。一个更完善的版本应该在解析学生回答后根据内容做简单判断并更新状态。我们可以这样增强def judge_and_update(state: TutorState, student_input: str, tutor_reply: str): 基于简单的规则判断学生上一轮回答是否正确。 生产环境可改用模型自动判断。 # 这里只是示例包含“不对”“不会”“不知道”时视为回答不理想 negative_markers [不对, 不会, 不知道, 不懂, 没思路] if any(marker in student_input for marker in negative_markers): state.record_wrong() print(f [状态更新] 连续答错次数: {state.wrong_count}) if state.wrong_count 3: # 达到阈值后向模型追加一条降难度提示 state.weak_points.append(需要降低难度) else: state.reset_wrong_count()这里的判断逻辑虽然简单但它展示了策略引擎的核心思想AI 的回复质量取决于我们是否能让状态参与决策。生产系统中你可以用更复杂的方式判断学生状态比如让模型输出结构化 JSON再解析到 state 对象中。5. 常见问题与排查思路在实际部署和二次开发 DeepTutor 或类似项目时大家会遇到不少问题。这里梳理几个高频场景问题现象常见原因解决思路调用 API 报 401 错误API 密钥配置错误或 .env 未加载检查 .env 文件和 load_dotenv 顺序模型总是直接给答案提示词约束不足增加具体规则采用 few-shot 示例强化约束对话几轮后效果变差历史消息过长模型注意力被稀释只传最近 3-5 轮或用状态摘要替代原始历史运行时报缺少依赖requirements.txt 版本不匹配按项目文档指定版本避免大版本升级高并发时延迟明显多次串行调用大模型引入缓存、异步并发、批量处理学生回答判断不准字符串规则太简单改用模型结构化输出让模型返回状态标签5.1 模型总是直接给答案怎么办这是 DeepTutor 类应用最容易遇到的问题。仅仅在 system prompt 里写“不要直接给答案”往往不够因为大模型对负向指令的遵循不如正向指令稳定。更有效的做法是提供负面示例few-shot。在提示词中给模型一个“错误示范”和“正确示范”模型会更容易模仿正确行为。例如错误示范 学生这道题怎么做 AI先用公式 x -b/(2a) 求出顶点横坐标然后代入得到纵坐标答案是 (2, -1)。 正确示范 学生这道题怎么做 AI你以前见过“顶点式”这个概念吗如果 y x^2 - 4x 3你觉得有没有办法把它变得更容易看出顶点增加后置检查。在主流程中接一个判断模型输出是否包含“答案句”的过滤器。如果检测到模型直接给出了完整答案可以通过二次调用要求它改成提问式引导。这相当于给 AI 导师增加了一层“审核机制”。5.2 状态管理导致越跑越偏怎么办我在前面的示例中提到了“状态摘要”方案。有些同学照着实现后会发现模型生成的反馈跟实际情况有点脱节。比如状态里写着“学生连续答错 3 次”但 AI 导师的回复还是在讲很难的内容。这种情况通常是因为状态信息在 prompt 中的权重不够高。可以尝试将状态摘要放到user消息开头而不是system消息。明确要求模型“必须根据当前会话状态调整回应方式”。在状态摘要中删除无关字段只保留与当前决策相关的字段。5.3 如何评估 AI 导师的水平评估 AI 导师不是简单测“准确率”因为启发式对话没有唯一标准答案。常用的思路是用一套“教学行为检查单”来做人工评测是否在连续 3 条回复中都没有直接给出完整答案是否在给出提示前先询问了学生的思路当学生答错时是否给出了针对性反馈而不是泛泛重讲是否在最后确认了学生的理解这套检查单可以作为打分表也可以让另一个更强的模型来打分。评估体系建议尽早建立否则很难判断提示词改动到底是变好还是变差。6. 工程化与教育场景落地建议如果产品已经过了 demo 阶段准备在生产环境落地那么下面这些方向值得提前规划。6.1 提示词版本管理DeepTutor 的核心能力高度依赖提示词。不同版本的提示词可能导致完全不同的教学风格。因此提示词应该像代码一样纳入版本管理并记录每次改动的效果对比。常见的做法是将每个版本的提示词单独命名例如math_tutor_v3。在评估系统中记录使用该版本时的会话质量分数。采用灰度发布策略先让 10% 的用户用新提示词版本对比效果后再全量推送。6.2 内容安全与未成年人保护教育场景往往面向未成年人内容安全是最高优先级。这里要特别强调几个边界第一AI 导师不得输出与学习无关的敏感内容。即使学生故意问一些与学科无关的话题AI 导师也应该礼貌拒绝并引导回学习主题。这可以通过提示词约束也可以在外层加内容过滤服务。第二AI 导师不应给出医疗、心理、法律等专业建议。学生可能趁机倾诉心事AI 不能越界充当心理咨询师。常规做法是在系统提示词中明确职责边界必要时输出固定话术“如果你感到不舒服建议告诉家长或老师。”第三数据隐私保护。学生的对话数据应加密存储访问权限要遵循最小权限原则。尤其是未成年人数据上线前务必完成合规评估。6.3 性能优化思路DeepTutor 类的应用本质上是一个“多轮交互系统”性能瓶颈主要在 LLM 推理。优化手段包括结果缓存对高频知识点问题可以缓存 AI 导师的引导步骤学生多次提问时不必每次都调用模型。异步接口将辅导过程拆分为“接收用户输入 - 异步生成回复 - 前端轮询结果”避免用户长时间等待 HTTP 响应。小模型前置路由先用一个轻量模型判断用户的意图和知识点分类再让大模型做深度辅导可以一定程度上降低成本。6.4 从原型到生产的完整链路演示项目可以只关注“对话质量”但生产环境还需要考虑学生提问 - 内容安全检查 - 知识点识别 - AI 导师对话 - 对话记录落库 - 会话总结生成 - 学习效果评估每一步都要有日志、监控和异常处理。尤其是 AI 导师的回复如果出现模型超时、输出格式异常、内容不合规等情况要有兜底策略。简单场景下可以在异常时返回“老师暂时走神了请重新说一遍”并把错误信息记录到日志中。7. 总结与下一步学习方向通过本文的梳理我们可以看到 DeepTutor 并不是一个简单的“大模型套壳”项目而是一个把教育学策略和 LLM 能力结合起来的智能体系统。它的核心贡献在于提出了“AI 导师应该如何引导学生思考”这一套可工程化的交互范式包括教学策略提示词、会话状态管理、学生画像追踪、学习效果评估等模块。我在实战部分搭建的 demo 虽然简化了很多细节但已经覆盖了 DeepTutor 风格应用的主干链路。你可以在此基础上继续做这样几件事把字符串规则升级为模型判断让模型输出结构化 JSON自动更新学生状态实现更精确的答题正误判断。接入学科知识库在学生与 AI 导师对话时利用 RAG检索增强生成从教材、题库中检索相关内容作为参考避免模型胡编乱造。尝试接入不同的基座模型不同模型对“启发式教学”提示词的遵循能力差异很大值得做一个横向测评。完善前端交互将命令行 Demo 改造成 Web 界面增加学生答题提交、过程记录展示、学习报告导出等功能。教育场景的 AI 应用有一个天然优势反馈链路短且明确——学生到底有没有学会很快就能通过测验体现。这给算法迭代提供了很好的依据。DeepTutor 的方向给教育智能体的发展提供了一个很务实的样本如果你也在做类似的学习产品建议直接 clone 一份源码看看从提示词设计开始逐步改造会比自己从零搭一套要快很多。希望这篇文章能帮你少走一些弯路。