港大开源AI学习系统:Agent架构与知识库错题集闭环
发布时间:2026/9/9 10:37:33来源:尧图网络
凌晨一点你对着屏幕上的几百页PDF讲义手里攥着错题本上红笔圈出的十几个反复出错的题型想找一套“能记住我上周哪里不会”的工具。普通的AI问答帮你查一道题可以但你问它“我最近一周在微积分上反复卡壳的是哪类题”它答不上来。因为它没有记忆也没有成长。港大团队开源的这套AI学习系统恰好瞄准了这个痛点。它的核心不是“又造一个聊天机器人”而是用原生Agent架构把知识库和错题集串成一个会持续成长的闭环。简单说它能记住你学过什么、练过什么、错在哪里然后动态调整下一次给你推荐什么内容。这是传统RAG知识库问答工具做不到的。这篇文章我会从架构角度拆解这套系统的设计思路然后给出一个最小可运行的Agent学习系统示例让你理解“知识库”和“错题集”在Agent内部是怎么协同的。读完你会发现所谓“神仙级”不只是AI答得准而是系统真的在陪你迭代。1. 为什么港大开源的AI学习系统值得关注先说结论这类系统的价值不在于“多了一个能回答问题的AI”而在于它把学习过程拆成了可以闭环优化的数据流。过去我们用在线题库、错题本、笔记软件这些工具彼此割裂。你做错的题在题库App里学习资料在云盘里笔记在Markdown里AI问答又单独开着另一个窗口。信息是碎片化的AI无法看到全貌也就无法提供真正的个性化学习建议。港大此前的多智能体工作也走在这一思路上强调的不是单个模型有多强而是把“任务拆解—工具调用—结果反馈”做成工程化组件。放到学习场景里这个系统天然适合处理三类任务第一把考生的学习资料统一清洗并向量化形成可检索的个人知识库第二把练习记录和错误答案沉淀下来生成结构化错题集第三在Agent的调度下让知识库和错题集互相联动比如检测到你连续三天在同一考点犯错就自动从知识库里检索对应讲解片段并生成新的变式题。开源意味着什么意味着你可以看到它的Prompt设计、记忆存储结构、工具调用链路而不是面对一个黑盒。对于想研究AI教育产品、Agent架构或者RAG落地的开发者来说这是一份非常高质量的教学样本。对于学生和终身学习者这类系统也在逐步降低个性化辅导的边际成本。当然这篇博客不会止步于夸它“好用”。我更想和你一起梳理清楚它到底改动的是技术架构的哪一层普通开发者能不能复刻一个简化版生产环境里接入要注意哪些坑这些问题才是真正决定你能否把它落地到自己项目里的关键。2. 原生Agent架构它和普通知识库问答工具有什么不同很多人一听到“知识库”立刻想到RAG检索增强生成。RAG的工作流程是用户提一个问题系统把问题向量化去向量数据库里召回最相关的文档片段再把这些片段连同问题一起交给大模型生成回答。这个流程没有状态用户上一次问什么、上一次错在哪里系统完全不知道。它适合“一次性答疑”但本质是“词典”而不是“老师”。标题里特意强调“原生Agent架构”这里的区别值得展开。Agent架构的基本单元是“感知—规划—行动—反思”。感知环节接收用户的当前问题同时读取系统已有的记忆规划环节决定先调知识库检索还是先查错题集行动环节调用检索、生成练习、记录结果等工具反思环节根据本次回答的反馈更新记忆。也就是说Agent体内自带一个循环而不是一次问答就结束。看一张简化对比表会更清楚维度传统RAG知识库问答原生Agent学习系统是否记录用户历史一般不记录有长期记忆模块回答是否依赖上下文只依赖当前问题和检索片段依赖历史错题、学习进度、偏好能否调用多个工具通常只能检索生成可自主决定调用检索/练习/复习工具是否动态更新数据知识库基本静态错题集和记忆会持续更新适合场景客服问答、资料查询个性化学习、长期陪练放到学习场景里这个架构的优势立刻显现。假设你正在学线性代数昨天做错了“矩阵的秩”相关题目今天你再问一个关于矩阵逆的问题。传统知识库只会根据你当前的问题返回相关讲义你昨天的错误对它没有任何影响。而Agent系统会先读取昨天的错题记录发现你对“秩”这个概念的理解有漏洞于是生成回答时会主动补充秩与可逆性的关系并在最后给你一道针对性的变式题。这里真正容易踩坑的地方在于多数人会把“原生Agent”理解成“大模型会自己思考”其实工程上的Agent核心是“记忆 工具 控制逻辑”模型只是决策大脑。港大这套系统的设计重心恰恰在于把学习过程中的记忆结构组织得足够好让Agent能在正确时机做正确的工具调用。理解了这一层后面所有代码和配置就都好懂了。3. 知识库与错题集AI学习系统的“长期记忆”设计如果说Agent是大脑记忆就是大脑里写满笔记的便签。在学习系统里记忆至少可以分成两层静态知识和动态反馈。知识库属于静态层负责承载课程讲义、教材章节、论文、例题解析等结构化或半结构化资料。静态不代表内容不变只是变化频率低。它的核心处理流程是清洗、切分、向量化然后写入向量数据库。用户在提问时Agent会从这一层检索相关片段作为回答的事实依据。错题集则属于动态层。每次用户答题系统会把题目、用户答案、标准答案、错误原因、关联知识点一并写入存储。这层数据变化非常频繁也最能体现个性化。普通工具也记录错题但只是展示列表Agent系统里的错题集是“信号源”它要解决的核心问题是判断哪些知识点是反复出错的真薄弱点并触发后续学习动作。这里要特别说一下知识库是不是一定放在向量数据库里。从热搜词里“ai智能体的企业知识库是存放在向量数据库中的吗”这类问题就能看出很多人对存储架构有误解。知识库源文件可以放在本地目录、对象存储或者Git仓库里向量数据库存的是“切分后的文本经过Embedding模型转换出来的向量”以及对应的原文引用。也就是说向量数据库是知识库的检索引擎不是知识库本身。错题集这类结构化数据则更常用关系型数据库或JSON文件存储需要强查询能力未必需要向量化。从数据流角度看学习Agent的长期记忆是这样运转的原始资料经过清洗和切分后进入文档存储向量化后进入向量数据库用户在Agent交互页答题和提问系统把答题结果写入错题存储Agent在每次问答前读取用户画像和近期错题Agent从知识库检索相关学习内容回答后根据反馈更新记忆。这样一个循环下来知识库越用越顺手错题集越来越精准系统给出的学习建议也会越来越贴合个人情况。港大这套系统的聪明之处就是把“知识库问答”和“自适应学习”这两件原本割裂的事通过Agent的控制循环融合在一起。它不再是一个被动的问答工具而是一个有状态、有反馈、会调整策略的学习伙伴。4. 环境准备与前置条件要把这套思路跑起来并不需要顶配设备。整个系统的资源消耗主要集中在Embedding模型和LLM推理上。如果只做单机Demo建议优先选择本地部署的轻量模型避免复杂的环境配置问题。以本文的简化示例为准你需要准备以下环境组件建议方案说明操作系统Linux / macOS / Windows WSL2保证Python和Docker可用Python版本3.10及以上新版LangChain或Agent框架普遍依赖3.10LLM后端Ollama qwen2.5:7b或同级别模型本地模型无需外网API调用Embedding模型bge-m3或同等级别用于文档向量化中英文效果较好向量数据库ChromaDB轻量文件级存储适合Demo和教学文档处理LangChain或自写切分逻辑本文演示用自写逻辑减少黑盒依赖版本细节请以你实际安装的为准这里不写死因为AI工具链迭代太快固定某个版本反而容易误导。建议用Python的虚拟环境管理依赖避免污染全局环境。设置好上面的基础环境后再准备一个目录放学习资料。不用贪多先用一两份Markdown格式的讲义做最小实验。比如一份线性代数笔记一份错题记录表。跑通之后再扩大到PDF和更多学科。注意PDF解析会增加很多工程细节新手第一版不建议直接上复杂格式。5. 核心流程拆解从知识录入到Agent自主调度一个可运行的Agent学习系统建设流程可以拆成六个环节第一步资料整理。把所有学习资料统一转成纯文本或Markdown去掉页眉页脚、重复广告和无意义符号。资料质量决定后面检索质量这一环节不能省。第二步知识库构建。将清洗后的文本按语义块切分每块控制在500到1000字之间块与块之间保留少量重叠避免上下文被切断。切分完成后做向量化写入向量数据库。这一步的产出是“可检索的知识切片”。第三步错题集建模。新建一个数据文件记录题目、选项、用户答案、正确判断、关联知识点、时间戳。错题数据不急着向量化因为它的主要使用方式是精确查询和统计推荐先用JSON或SQLite存储。第四步Agent工具定义。给Agent注册两个核心工具检索知识库用于输入问题后返回相关讲义片段记录错题用于把一次答题结果写入错题存储。工具定义要包含名字、参数说明和返回说明这是Agent能正确调用的前提。第五步Agent调度逻辑。写一个循环接收用户输入判断是“提问”还是“答题”如果是提问先检索知识库同时读取最近错题记录如果是答题则调用批改逻辑把错题写入存储再决定是否需要补充讲解。关键点在于让Agent先看错题历史再决定回答策略。第六步效果验证。用几个预设问题测试系统看知识库召回是否准确、错题记录是否写对、再次提问时系统是否能参考历史错误。整个流程中最容易出问题的是第二步的切分。切得太碎语义不完整切得太粗向量检索召回会掺入无关内容。建议按Markdown标题层级切分先按章节再按段落必要时补充重叠句。6. 完整示例一个最小可运行的Agent学习系统为了让思路落地我写了一个精简实现。它不是港大原项目的复刻而是把核心机制提炼成可运行的示例方便你理解知识库和错题集在Agent内部如何协同。先看项目结构learning-agent-demo/ ├── requirements.txt ├── data/ │ ├── knowledge_base.md │ └── mistake_records.json ├── agent_config.yaml ├── knowledge_store.py ├── agent_loop.py └── run.sh这是一个非常克制的目录结构每个文件都有单一职责。如果你希望在生产环境扩展可以在其中加入更完整的日志、配置中心和用户系统但教学场景保持简洁更好。6.1 安装依赖python -m venv .venv source .venv/bin/activate # Windows 使用 .venv\Scripts\activate pip install langchain langchain-community langchain-ollama chromadb pyyaml这份依赖清单只包含跑通Demo所需的核心库。生产环境如果要加PDF解析、用户体系或更复杂的向量数据库再按需补充不必一次性装很多包。6.2 准备学习资料和错题文件# 文件路径data/knowledge_base.md ## 第一节矩阵的秩 矩阵的秩定义为矩阵中最高阶非零子式的阶数。 秩与可逆性n阶方阵A可逆当且仅当rank(A)n。 常见结论秩为r的矩阵可以通过初等变换化为阶梯形非零行数为r。// 文件路径data/mistake_records.json { records: [ { id: 1, question: 当矩阵A的秩为n时A是否可逆, user_answer: 否, is_correct: false, knowledge_point: 矩阵的秩与可逆性, timestamp: 2025-01-08T10:00:00 } ] }错题JSON已经预先放入一条记录便于测试“Agent能看到历史错误”的能力。实际使用中这些记录由批改模块动态写入。6.3 知识库构建与检索# 文件路径knowledge_store.py from langchain_ollama import OllamaEmbeddings from langchain_chroma import Chroma from langchain.text_splitter import MarkdownHeaderTextSplitter from pathlib import Path def build_knowledge_store(): text Path(data/knowledge_base.md).read_text(encodingutf-8) headers_to_split_on [(#, H1), (##, H2)] splitter MarkdownHeaderTextSplitter(headers_to_split_on) docs splitter.split_text(text) embeddings OllamaEmbeddings(modelbge-m3) vector_store Chroma.from_documents( documentsdocs, embeddingembeddings, persist_directory./chroma_db ) return vector_store def search_knowledge(query: str, top_k: int 3): embeddings OllamaEmbeddings(modelbge-m3) vector_store Chroma( persist_directory./chroma_db, embedding_functionembeddings ) results vector_store.similarity_search_with_score(query, ktop_k) return [(doc.page_content, score) for doc, score in results] if __name__ __main__: build_knowledge_store() print(知识库构建完成)这段代码把Markdown按二级标题切分后直接向量化写入ChromaDB。对入门项目来说Markdown结构本身就是很好的切分依据能减少很多文本清洗工作量。运行一次构建成功后search_knowledge函数就被后面的Agent调用。6.4 Agent调度逻辑# 文件路径agent_loop.py import json from pathlib import Path from knowledge_store import search_knowledge from langchain_ollama import ChatOllama MISTAKE_FILE Path(data/mistake_records.json) def load_mistakes(): data json.loads(MISTAKE_FILE.read_text(encodingutf-8)) return data[records] def record_mistake(question, user_answer, is_correct, knowledge_point): records load_mistakes() records.append({ id: len(records) 1, question: question, user_answer: user_answer, is_correct: is_correct, knowledge_point: knowledge_point, timestamp: 2025-01-08T11:00:00 }) MISTAKE_FILE.write_text( json.dumps({records: records}, ensure_asciiFalse, indent2), encodingutf-8 ) def build_prompt(question: str, context: str, mistakes: list) - str: mistake_summary .join([m[knowledge_point] for m in mistakes]) return f 你是一名耐心的一对一学习教练。 已知知识库片段 {context} 用户历史上在以下知识点出过错{mistake_summary} 如果本次问题与上述知识点相关请先解释基础概念再给出一道变式题。 用户问题{question} def agent_answer(question: str): llm ChatOllama(modelqwen2.5:7b, temperature0.2) if 帮我批改 in question: record_mistake( question示例题当矩阵A的秩为n时A是否可逆, user_answer否, is_correctFalse, knowledge_point矩阵的秩与可逆性 ) return 已记录错题后续会针对性复习。 else: context_items search_knowledge(question) if not context_items: return 知识库中没有检索到相关内容请先整理讲义。 context \n.join([content for content, _ in context_items]) mistakes load_mistakes() prompt build_prompt(question, context, mistakes) response llm.invoke(prompt) return response.content if __name__ __main__: while True: q input(请输入问题输入 q 退出) if q.lower() q: break print(agent_answer(q))这个文件展示了最小化的Agent控制循环。它没有引入复杂框架核心是用一个if-else区分“答题记录”和“知识问答”再在问答Prompt里注入历史错题。这就是原生Agent架构的雏形有工具调用检索、记录有记忆读取错题列表有一层简单的决策逻辑。6.5 启动脚本# 文件路径run.sh #!/bin/bash echo 请确认Ollama中已拉取 bge-m3 和 qwen2.5:7b 模型 python knowledge_store.py python agent_loop.pychmod x run.sh ./run.sh先执行知识库构建再启动Agent交互循环。这里故意把两步拆开是因为知识库不需要每次问答都重建实际项目中建议做成定时任务或增量更新。7. 运行结果与效果验证按上面步骤跑通后你会在终端看到交互提示。建议依次测试三种场景验证系统是否符合预期。场景一直接提问知识库内容。请输入问题矩阵的秩与可逆性有什么关系预期回答里应包含知识库片段中的“n阶方阵A可逆当且仅当rank(A)n”并且因为错题记录里有同一知识点回答应该主动补充基础概念讲解判断用户上次在这里错过。场景二触发错题记录。请输入问题帮我批改一道题程序会向错题JSON写入一条新记录。处理结束后你打开data/mistake_records.json能看到records数组多了一条数据。场景三验证记忆能力。先再执行一次场景二然后继续提问矩阵秩相关内容。此时Agent的历史错题列表里已有多条“矩阵的秩与可逆性”记录回答会更强调概念矫正。如果回答和普通RAG没有区别第一步检查Prompt里是否成功读取了错题文本。因为Agent的记忆能力完全依赖这一环节。其次检查知识库检索返回的上下文是否正确可在代码里临时打印context_items确认召回结果。如果回答中断或报错优先确认Ollama服务是否运行以及模型名是否拼写正确。终端执行ollama list能看到模型列表才算就绪。如果知识库检索返回空需要看构建阶段是否有报错并检查data/knowledge_base.md内容是否为空。Chroma目录如果之前已生成也可以删除后重新构建避免脏数据影响。8. 常见问题与排查思路以下是这个Demo以及类似Agent学习系统里最常遇到的几类问题。问题现象可能原因排查方式解决方案知识库检索永远返回空向量数据库未构建成功或路径错误检查终端有没有“知识库构建完成”删除chroma_db目录重新运行构建脚本Agent回答里看不到错题影响Prompt没有注入错题记录打印build_prompt生成的完整Prompt确认load_mistakes读取到非空JSON回答非常慢本地7B模型在CPU上推理查看系统资源占用和Ollama进程CPU换更小模型如qwen2.5:3b回答质量差不遵循指令模型太小或temperature过高检查有没有按配置文件设temperature降低temperature到0.2以下换7B以上模型错题JSON越写越大查询变慢没有做按时间/知识点索引用SQLite替代JSON文件生产环境迁移到SQLite或PostgreSQL向量化中文效果差Embedding模型不支持中文检查模型名称和文档语言换bge-m3等中文优化模型文本切分导致检索结果不完整Markdown标题切分过粗打印切分结果查看块大小对长内容补充段落级切分或重叠窗口这里更想提醒的是Agent学习系统的排错顺序应该从数据到模型再到逻辑不要一上来就怀疑大模型“不会思考”。大多数表现不佳根源都在知识库切分不干净、错题记录没写对或Prompt上下文没有真正注入而不是模型能力不行。还有一个容易被忽略的问题错题记录里如果涉及用户敏感信息生产环境落地时一定要做脱敏和访问控制。学习数据比普通日志更私密一旦泄露后果比想象中严重。9. 最佳实践与工程建议看完Demo再聊聊生产环境里的工程建议。Demo的价值是帮助你理解原理但如果真的要做成面向大量用户的学习系统有几个点必须提前设计好。第一知识库做版本管理。讲义会更新课程会迭代如果直接覆盖向量库历史索引会不一致。建议知识库源文件放入Git仓库配合CI/CD在提交时触发向量化流水线。每次构建记录版本号用户查询时能知道自己使用的是哪个版本的知识。第二错题集不要只存“答案对错”还要存推理过程。很多教育产品只记录正确与否这是远远不够的。错题真正有价值的是错误答案、解题步骤和用户的思考过程。把这些记录下来Agent才能分析出是概念不清还是计算失误给出的解释也才更精准。第三Agent需要人在回路上。不要一上来就全自动更新错题和推荐内容。早期建议采用“建议模式”Agent产出分析报告用户确认后再写入记忆。错题记录一旦写错后续所有推荐都会被污染。你可以先让Agent“建议标记某题为错题”用户确认后生效这样能保证记忆质量。第四召回策略要回归测试。知识库不可能一次性做到完美建议准备一组标准测试题每次调整切分方式、Embedding模型或Prompt后都跑一遍回归测试确保老问题没退化。这类测试集应该沉淀在项目仓库里作为质量基线。第五控制LLM权限。Agent如果具备写错题、发通知、操作外部系统的能力务必将这些工具的执行范围做成白名单并在执行后加入可撤销机制。涉及删除操作时更推荐逻辑删除而不是物理删除方便回滚。第六设计交互时要考虑用户的学习目标而不是只满足提问。系统界面最好能展示知识图谱和薄弱点分布让用户看到Agent“理解”了哪些内容。透明性会显著提升用户对系统的信任度也会让错误记忆更容易被发现。10. 总结与后续学习方向港大开源这套AI学习系统真正的看点不是“又有一个能聊天的AI”而是把Agent架构、知识库、错题集组合成了一个有记忆、有反馈的学习循环。它像一个耐心的同行者既记得你昨天错在哪里也知道今天该给你讲什么。这种设计思路本质上代表了AI教育产品从“被动问答”向“主动陪练”演进的趋势。如果你想把这篇博客的Demo跑起来建议按这个顺序操作先准备Ollama和模型再跑知识库构建脚本最后进入Agent交互循环。跑通后可以做的第一个改进是把JSON错题存储换成SQLite再往后可以接一套Web界面让用户能在浏览器里直接使用。深入方向则可以考虑研究多Agent协同补全参考LangGraph或更成熟的多Agent框架来替代Demo里的手工if-else逻辑探索更细粒度的记忆分层把短期对话记忆和长期错题记忆分开管理加入复习计划调度算法让系统不只会“推荐”还会“排期”。这套系统还在快速发展期真正吃透它的最好方式就是打开源代码跟着数据流走一遍再改造成适合自己的版本。希望这篇拆解能让你少走一些弯路也欢迎在评论区交流你的实现细节和踩坑记录。
网站建设高端定制企业官网