乐于分享
好东西不私藏

从零到一构建AI学习助手:agent搭建技术实践

从零到一构建AI学习助手:agent搭建技术实践

写在前面

本系列记录一个agent产品的构建过程。

当我决定开源这个项目时,脑海中闪过的第一个念头是:能不能通过 Build in Public 的方式,让更多人看到一个 AI 产品从概念到落地的完整过程?不是那种“三天速成”的教程,而是真实的踩坑、试错、推翻重来。

这个项目要解决的问题很具体:笔记软件用户“只记不学”的困境,以及K12 中小学教师大量出题的负担。技术方案也很直接:将 Markdown 或 PDF 文件向量化存储,然后通过 AI Agent 以出题、提问等方式帮助用户真正消化知识。


关键决策:架构范式的选择

在开始coding之前,我花了很长时间研究优秀的开源Agent项目。其中一个核心发现改变了整个项目的走向:Tool-Based Delegation(工具即路由)这个设计模式。

传统的Agent架构依赖大量的条件判断——如果用户说了A,就走流程X;如果说了B,就走流程Y。这种方式在复杂场景下会变成难以维护的意大利面条代码。

而Tool-Based架构的核心思想是:让大模型通过阅读函数的文档注释来决定系统走向。你不需要告诉AI“如果用户说‘出题’就调用 examiner”,而是给AI 提供一个名为delegate_to_examiner的工具,在它的docstring里详细描述“什么时候应该用这个工具”。

这个设计哲学把路由逻辑从代码层提升到了语义层,让系统具备了真正的“理解能力”。


第一部分的实践过程

Part1 环境搭建与模型接入

在选择基础模型时,必须明确验证它对核心能力的支持程度。在开发过程中,我选择了DeepSeek API,它的Function Calling能力表现出色,参数提取准确率很高。

Part2 状态管理的精细设计

Agent的状态管理是整个系统的神经中枢。我需要追踪三类关键信息:

  • 对话历史(messages)

  • 已加载的文档列表(documents_loaded)

  • 用户的错题记录(wrong_questions)

关键的是 Reducer 函数的设计。对于wrong_questions这个字典类型的状态,我需要实现“累加而非覆盖”的合并逻辑。参考优秀开源项目的实现,我使用了 {**existing, **new} 这个Python字典解包技巧,简洁地实现了新值覆盖同key旧值的语义。

还有一个细节值得记录:remaining_steps字段。这是LangGraph的create_react_agent内部要求的必需字段,但官方文档里没有明确说明。我是通过运行时报错信息反向推导出来的:

ValueError: Missing required key(s) {'remaining_steps'} in state_schema

part3 工具设计的灵魂——Docstring

我设计了三个delegate工具:

  • delegate_to_ingestor:处理文档上传和解析

  • delegate_to_tutor:回答学习问题和知识讲解

  • delegate_to_examiner:生成测试题目和考试

关键在于:大模型看不到你的Python代码实现,它只能看到函数名、参数类型和docstring

所以docstring不是写给程序员看的,而是“写给AI看的产品说明书”。在参考优秀开源项目后,我为每个工具编写了详尽的使用说明:

"""Delegate exam generation tasks to the Examiner sub-agent.

Call this tool when the user wants to be tested, quizzed, or wants
practice questions generated.

When to use this tool:
- User asks for a quiz, test, or exam
- User says "给我出题" or "考考我"
- User wants to practice specific topics

When NOT to use this tool:
- User just wants an explanation -> use delegate_to_tutor
- User wants to upload a document -> use delegate_to_ingestor

Args:
    topics: List of knowledge topics to cover in the exam
        (e.g. ["机器学习", "线性回归", "梯度下降"])
    num_questions: Number of questions to generate (default: 5)
    difficulty: Difficulty level: "easy", "medium", or "hard"
"""

这种写法的效果立竿见影。在测试中,当用户说“我不太理解什么是反向传播,给我讲讲”时,系统准确地路由到了 delegate_to_tutor;而当用户说“请给我出5道关于线性回归的题”时,系统不仅选对了delegate_to_examiner,还精确提取了topics=[“线性回归”]num_questions=5这两个参数。

Part4 无边图架构的验证

LangGraph的create_react_agent提供了一个开箱即用的ReAct循环:

  1. Agent节点:调用LLM决定是否使用工具

  2. Tools节点:执行选中的工具

  3. 条件边:自动判断是继续循环还是结束

这个设计契合“无条件边”的理念——你不需要手动定义“什么情况下从A节点跳到B节点”,框架会根据LLM的输出自动路由。

但在实现过程中,我遇到了一个环境问题:SSL 证书路径错误。Conda环境激活时自动设置了SSL_CERT_FILE环境变量,指向一个不存在的文件。解决方法很简单粗暴:在所有入口文件顶部加上 os.environ.pop("SSL_CERT_FILE", None)。

最终的端到端测试结果令人满意:

用户输入
系统路由
参数提取
“帮我把/data/ml.pdf导入系统”
delegate_to_ingestor
file_path="/data/ml.pdf"
“我不理解反向传播”
delegate_to_tutor
topic=“反向传播”
“出5道中等难度的线性回归题”
delegate_to_examiner
topics=[“线性回归”]

num_questions=5difficulty="medium"

产品思考:技术选型背后的用户价值

以产品经理视角来思考:这些技术决策最终会如何影响用户体验?

Tool-Based 架构的产品价值:用户不需要学习特定的命令格式。他们可以用自然语言表达意图,系统会自动理解并路由到正确的功能模块。这降低了学习成本,提升了交互的自然度。

状态管理的产品价值:通过持久化错题记录,系统可以实现“针对性复习”——下次出题时优先考察用户之前答错的知识点。这是传统笔记软件做不到的。

模型选择的产品价值:DeepSeek 的 Function Calling 准确率直接决定了系统的“理解能力”。如果模型频繁误判用户意图,整个产品体验就会崩塌。


踩过的坑与经验总结

  1. 类型兼容性问题要在项目初期就明确。Python 版本、依赖库版本的不一致会在意想不到的地方引发问题。

  2. Docstring 是 AI 时代的新型 API 文档。它不仅要说明“这个函数做什么”,更要说明“什么时候该用它,什么时候不该用”。

  3. 测试驱动的开发在 Agent 项目中尤为重要。每个工具、每个状态转换都应该有对应的测试用例,否则很难发现路由逻辑的 bug。

  4. 选择成熟的开源项目作为参考,但不要盲目照搬。理解设计理念比复制代码更重要。


下一步计划

第一部分只是搭建了主控框架,真正的挑战还在后面:

  • 实现文档向量化的 Ingestor 子 Agent

  • 设计自适应难度的 Examiner 出题算法

  • 构建知识图谱增强的 Tutor 讲解能力

  • 优化多轮对话的上下文管理

我会持续以 Build in Public 的方式分享本agent过程,记录下一个产品从0到1的真实轨迹——包括那些弯路、失败和顿悟时刻。

如果你也在构建AI产品,或者对这个领域感兴趣,欢迎关注后续更新。我们可以一起探讨技术方案,分享踩坑经验,见证AI如何真正改变学习方式。


技术栈:LangGraph + LangChain + ChromaDB 
适用场景:个人学习笔记消化、K12 教师出题辅助

Build in Public 让我们一起构建项目。