
说实话这个项目一开始只是我给自己做的“私教工具”。当时我一边上班一边准备一个技术方向的学习计划每天要啃好几篇英文文档还得对着屏幕做笔记、刷题、整理错题。用在线大模型问答确实方便但有两个问题一直让我很别扭一是我的笔记、计划、错题全都得传到别人服务器上心里始终不踏实二是网络情况不好的时候整个学习节奏直接断掉。后来我索性动手做了个本地 AI 学习软件让模型和数据全都跑在本地电脑上然后把它整理成了一个免费开源项目。现在这软件已经能实现资料问答、自动出题、错题复盘、背卡复习这些功能全程离线不联网、不上传任何个人数据。如果你也是那种注重隐私、习惯长周期学习、或者想让学生在自己的电脑上使用 AI 但不想依赖云服务的场景那这篇文章应该对你有用。我会把整个项目的设计思路、技术选型、实操部署过程、还有我踩过的坑尽量完整地分享出来。不光是给你看代码和效果更重要的是说清楚每一步为什么这么做这样你拿到源码之后既能跑起来也能改得动。1. 为什么要做一个“本地运行”的学习软件很多朋友一听“本地 AI”第一反应是“显卡要求很高吧”、“是不是又难又慢”。这个刻板印象我得先帮大家打碎一点。现在的中小尺寸开源模型配合高效的量化方案已经完全可以在普通家用电脑上跑出可用的效果。我下面把自己做这个决定时的几个核心考虑拆开讲。1.1 在线 AI 做学习工具的两个硬伤在线大模型确实聪明但把它当成学习工具用的时候有两条硬伤很难绕过去。第一是隐私问题。学习资料和笔记这东西比聊天记录更敏感。你的复习提纲、错题本、知识盲区、学习进度这些数据本身没有太大商业价值但它们非常“个人”。我实在不太愿意让它们每天被打包上传到某个云端去做分析和脱敏。更不用说如果是给学生用还要额外考虑未成年人的数据合规问题。把模型放到本地数据不出设备这个物理边界比任何隐私协议都让人放心。第二是依赖性问题。在线学习工具依赖网络、依赖服务商的可用性、依赖账号体系的稳定性。别小看这一点我实测过在图书馆、地铁站、宿舍这些场景里网络波动非常正常而学习恰恰是最讲究“连续感”的事情。你正问到一半突然断线整个思路就断了等重新恢复连接你又要花十分钟回到原来的问题状态。本地运行天然没有这种中断模型就住在你电脑里点击即用、断网可用。1.2 现在的本地模型已经“够用”了这里说的“够用”是指针对学习场景足够用。学习工具需要的不是写诗编故事的能力而是稳定的理解、检索、归纳和出题能力。像 Qwen2.5 7B、DeepSeek-R1-Distill-Qwen 7B 这样的开源模型量化到 Q4_K_M 之后在最新几代 CPU 或入门级独显上都能跑起来回答质量对于“解释概念”、“总结要点”、“根据知识点出题”这些任务已经非常能打了。还有一个容易被忽略的点学习场景里的模型不需要“什么都知道”它更需要“理解你给它的那部分材料”。所以本地模型重点不是拼参数而是配合知识库检索在规定范围内给出准确回答。这种架构下7B 模型在知识库约束下给出的答案往往比大参数通用模型瞎猜更加可靠。1.3 最终确定的产品定位经过上面这些分析我把产品定位总结成了四句话本地运行模型、数据、服务全部跑在用户自己的机器上学习专用不做大而全的聊天助手只围绕学习流程设计功能免费开源不卖账号、不搞订阅彻底开源方便二次开发离线优先没有网络也能完整使用符合长期学习场景。这个定位基本就是我最初的核心需求后来项目的所有功能、架构、技术选型都是围绕这四句话展开的。2. 整体功能设计与技术架构拆解定好方向之后我开始做功能设计和架构选型。这个阶段我反复推敲了很久因为一旦架构跑偏后面返工成本很高。2.1 功能模块划分我参考了真实学习闭环输入材料 → 理解加工 → 主动回忆 → 检测掌握 → 查漏补缺做出了五个相互独立的模块。第一个是“资料问答”模块。它的作用是把用户上传的 PDF、Markdown、TXT 文档做切片和向量化然后基于这些资料回答问题。这个模块不是简单地让模型“读全文”而是用检索增强的方式先从知识库里找到相关内容再让模型基于这些内容组织答案。这样又能定位原文出处又能在资料特别长的时候保持回答准确。第二个是“自动出题”模块。用户选一个知识范围设定难度和题型系统会结合知识库内容生成选择题、填空题、简答题。我特意做了一个“答案分离”的处理生成题目时同时生成答案和解析但练习模式下答案不直接显示只有当用户提交之后才回显。第三个是“错题复盘”模块。每次练习的记录都会存进本地数据库答错的题目会自动进错题集系统会定期安排重做还会根据错题涉及的知识点反查知识库把相关原文重新推送给用户。第四个是“背诵卡”模块。基于间隔重复算法把用户需要记忆的知识点生成卡片按记忆曲线的节奏提醒复习。这个模块本质上是一个本地版的记忆辅助工具但卡片的来源不只是手动输入也可以从问答记录中自动抽取。第五个是“学习统计”模块。记录学习时长、提问数量、正确率、知识点覆盖情况并且全部停留在本地用简单的图表展示出来。数据存在 SQLite 里导出就是一整个文件用户自己也能拿去备份。这五个模块并不炫技但我发现它们正好补上了通用 AI 聊天工具在学习场景里的空缺通用 AI 只会被动回答而这套系统会围绕学习闭环主动帮用户复习和检测。2.2 技术选型与理由技术选型上我坚持一个原则尽量选成熟、稳定、有社区基础的东西不做花里胡哨的自研。下面是每个层面我最终的选择和理由。模型加载层用的是 Ollama。它的优势是安装极其简单跨平台表现稳定而且对量化模型的支持非常友好。Ollama 提供 HTTP API我不用自己去写推理服务直接拉取模型就能跑这对项目初期的快速迭代帮助非常大。如果你更想自己控制推理细节也可以换成 llama.cpp 自己编译但 Ollama 对普通用户更友好也更适合课程的场景。后端框架用的是 Python FastAPI。选它是因为 RAG 链路里涉及文本切片、向量化、检索这一套 Python 生态非常成熟。FastAPI 自带 OpenAPI 文档调试起来非常直观后面我把前端做出来之后接口联调效率也高。整个后端服务跑在本地默认 8000 端口不监听外部网络。前端用的是 Tauri配合 Vue 3。不用 Electron 的原因很实际Tauri 安装包体积小内存占用低这在本地部署场景里非常重要。因为本地推理本来就吃内存和 CPU如果前端框架再吃掉几百 MB整体体验会很差。Tauri 的 WebView 渲染在 Windows、macOS 和主流 Linux 发行版上都没有问题。向量数据库用的是 ChromaDB。它在单机场景下的表现很稳定免服务一个文件夹就是整个库备份和迁移非常方便。对于学习软件这种个人级使用场景ChromaDB 的检索速度完全够用。我实测过一个 500 页 PDF 建立索引之后单次检索的延迟在几十毫秒级别瓶颈主要还是在模型生成阶段。以上这套架构全部组件都是免费开源软件所以项目本身可以放心开源分发不用背着授权包袱。2.3 一个被很多人忽略的设计强制本地代码覆盖这一节聊聊我在开发过程中遇到的一个实际问题。Tauri 的构建产物里前端静态资源是打包在可执行文件里面的但开发模式下前端代码跑在本地开发服务器上。如果用户改动了前端代码然后重新 build旧缓存偶尔会导致界面显示的还是旧版本。这就是大家常说的“强制覆盖本地代码”问题。我一开始先正常构建再手动覆盖资源文件结果在 Windows 上发现部分用户系统里界面始终是旧版本换了几个清理工具都不行。后来定位到原因Tauri 在 Windows 下会把静态资源写入 WebView 的缓存目录普通的文件替换不会自动让前端重新拉取新文件。解决方式有两个都在项目里实现了。一是给每次构建打上唯一版本号在 index.html 里通过一个不参与缓存的参数引用 CSS 和 JS 文件二是提供force-reload清理指令用户可以在设置页一键点击前端会调用后端接口清除本地缓存目录里相关的旧文件。这两种方式合在一起实测下来能彻底解决“改了代码但页面没变”的情况。这个细节对普通用户来说可能无关紧要但对开源项目的贡献者来说特别重要。因为开源项目一个很大的价值就是让别人能在你代码基础上修改如果连本地覆盖代码都不可靠会直接把一批潜在贡献者挡在门外。3. 从零复现核心实操与实现过程下面进入实操部分。我会按照自己在全新机器上部署这套软件的完整顺序来讲尽量具体到命令和参数方便你直接照着做。3.1 环境准备与依赖安装基础环境是三件事Python 3.10 及以上版本、Node.js 18 及以上版本、Rust 工具链。Python 负责后端Node.js 负责前端构建Rust 负责 Tauri 壳编译。如果你只想跑核心学习功能不打算重新编译前端安装包那么 Rust 可以先不装直接通过 Tauri 的预编译资源跑开发模式也行。我把后端依赖写在一个requirements.txt里核心依赖如下fastapi uvicorn chromadb sentence-transformers pypdf markdown-it-py ollama安装命令就是标准的cd server pip install -r requirements.txt如果是在国内网络环境下安装需要注意 PyPI 源的问题。常见做法是临时指定清华镜像源命令如下。这不是什么特殊操作只是普通开源项目在国内环境安装依赖的标准实践。pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple前端部分进入web目录后执行npm install这一步会把 Vue 3、Vite 和相关依赖装好。如果网络慢也可以把 npm registry 切换为国内镜像方式和 pip 类似只是命令换成npm config set registry https://registry.npmmirror.com这个步骤做完开发环境就基本齐了。3.2 下载并配置本地模型模型这块我强烈建议从 Ollama 开始。先安装 Ollama然后拉模型整个过程是ollama pull qwen2.5:7b-instruct-q4_K_M这条命令会下载一个约 4.7 GB 的量化模型。Q4_K_M 是 4-bit 量化中质量折中最好的一个档位大家不用再研究其他方案直接选它就行。如果你机器的内存或者显存比较紧张也可以选择qwen2.5:3b-instruct-q4_K_M文件约 2 GB运行更流畅但回答详细程度会弱一截。我自己的测试机是一颗六年前的 i7 处理器加 GTX 1660 显卡6 GB 显存跑 7B 量化模型大概每秒生成 12 到 18 个 token。用于“读资料、出题、解析”这类学习场景是完全够用的因为它每次回答的字数不像聊天那么夸张。配置模型时我还做了一层抽象后端服务启动时会读取config.yaml里面指定了当前使用的模型名、上下文长度和温度参数。我的推荐值是上下文 4096、温度 0.3。温度为什么设置得低因为学习场景要的是稳定、准确、可复现的回答。如果温度太高同一个问题问两次答案会跑偏这对学习来说反而是干扰。练口语、头脑风暴才需要高温度做题和讲解必须低温。3.3 知识库构建与向量化检索知识库是本项目的重头戏。整个流程是文档解析 → 文本切片 → 向量化 → 写入数据库 → 检索。文档解析我用的是pypdf对 PDF 的兼容性比较好。切片环节我固定按 300 到 500 字符切一块重叠 50 字符。为什么要重叠因为如果正好在一个概念的中间切断后面检索的时候上下文会不完整重叠能有效缓解这个问题。这个参数不是玄学是用多处文档测试之后得出来的经验值。向量化模型用的是sentence-transformers里的paraphrase-multilingual-MiniLM-L12-v2它支持多语言中文效果可接受模型体积小在本地 CPU 上跑速度也很快。如果你对中文知识库质量有更高要求可以换成BAAI/bge-small-zh-v1.5效果会更好代价是首次向量化时间稍长一些。下面是知识库构建核心代码的一个简化版本from chromadb import Client from chromadb.config import Settings client Client(Settings(chroma_db_implduckdbparquet, persist_directory./kb_store)) collection client.get_or_create_collection(my_knowledge) def add_document(title, chunks): for idx, chunk in enumerate(chunks): collection.add( ids[f{title}_{idx}], documents[chunk] )写入之后检索的时候就比较简单只用把用户的问题向量化然后查询 top-kk 一般选 4 到 6 条。检索的结果会拼接成提示词交给模型回答。这里注意提示词里必须带上“只根据以下资料回答不要编造”的约束同时把原文片段和出处标注一起传进去。这样模型给出的回答即便跑偏用户也能顺着出处回去核对原始材料。3.4 学习模块的关键实现自动出题模块是我写起来最有成就感的部分核心思路听起来其实不复杂把知识库的若干切片作为出题材料向模型请求生成题目题目用 JSON 格式返回系统解析后存入 SQLite。举个例子提示词大致是这样prompt f 根据以下材料生成3道单选题并给出答案和解析。 要求 1. 题目紧扣材料不超纲 2. 干扰项要有迷惑性 3. 用JSON数组返回格式 [{{question: ..., options: [A. , B. , C. , D. ], answer: A, explanation: ...}}] 材料 {context} 这里有个非常重要的工程细节本地模型输出 JSON 偶尔会出现格式残缺。所以我加了一个容错解析层先尝试用严格 JSON 解析失败之后用正则从文本里提取结构再失败就把这段输出标记为“生成异常”不让它进入题目库。宁可少一道题也不让脏数据污染错题记录。错题复盘和背诵卡模块本质上都是对 SQLite 表格的增删改查。错题表里记录题目内容、用户答案、正确答案、知识点标签、错误次数背诵卡的复习时间由interval字段动态更新。间隔重复算法的初始间隔定为 1 天之后每次复习正确间隔翻倍上限 30 天如果复习错误间隔重置为 1 天。这个就是非常朴素的记忆曲线逻辑不需要复杂公式也能有效。整个后端就这些东西没有魔法核心就是把“学习流程”翻译成“检索 生成 存储 定时提醒”这四类操作。4. 部署和日常使用中踩过的坑这部分是文章里最有保留价值的部分。每个问题我都实际遇到过并且在项目排错文档里做了记录这里挑四个最典型的分享出来。4.1 模型服务“起不来”日志却很干净的常见原因我遇到的第一次假死是后端提示连接 Ollama 失败但 Ollama 的窗口明明是开着的。排查了半天发现问题是 Ollama 的默认服务只绑定了127.0.0.1:11434而我在启动后端时用了localhost在某种代理环境下localhost被解析成了::1也就是 IPv6 回环地址结果服务连不上。解决办法很简单把后端配置里的模型接口地址写死为http://127.0.0.1:11434。这个问题在 Windows 和 Linux 下都容易出现建议大家写代码时尽量避免依赖localhost的自动解析。4.2 显存不够导致的生成卡死7B 模型量化之后虽然显存占用被压到了一个可观的范围但 6 GB 显存的机器还会碰到一个问题系统自带的桌面合成器也会占用一部分显存再加上输入输出的临时缓冲区跑着跑着就 OOM 了。表现是模型刚开始生成几个字然后整个程序像卡死一样没有任何输出。解决方式是限制生成的最大长度。我最终把单次生成的num_predict设为 2048同时在系统层面把 Ollama 的OLLAMA_MAX_LOADED_MODELS环境变量设为 1确保同一时间只加载一个模型避免多个模型同时驻留显存。这样设置之后连续使用几小时也没有再卡死过。4.3 检索结果与问题不匹配这可能是所有 RAG 项目里都会遇到的问题。我一开始把 top-k 设成 8本意是多给模型一些上下文参考结果发现回答质量反而下降。原因是检索出来的片段里相关性不高的部分占了多数模型被一些无关信息带偏了。经过多轮对比测试我把检索结果调整为 6 条同时加入一条基于关键词相似度的过滤逻辑如果某条检索结果的相似度分数明显低于其他条目就直接丢弃。另外在提示词里明确告诉模型忽略与问题无关的内容。这个组合下来回答准确率提升得非常明显。4.4 开源项目发布时最容易忽略的授权问题做开源项目代码能不能被别人自由用是一个绕不开的话题。我这里不是说法律条款本身而是说一个工程层面的坑项目里如果引用了其他开源组件即便你自己是 MIT 授权也不意味着整个项目就“干净”了。当时我引入了两个相对冷门的 npm 包来处理文本导出其中一个是 GPL 授权这意味着整个前端项目的开源授权都会受到传染式影响。发现这个问题之后我把这两个依赖替换成了自己写的简单实现同时也把 Ollama、ChromaDB 这类外部依赖标注为“运行时建议非内置”。开源不是把代码一丢就完事把这些引用关系整理清楚是项目想要长期健康发展的基本素质。这一点我专门在 README 的授权说明部分写了一段给所有想二次开发的人省心。5. 实际使用体验和可以继续扩展的方向软件基本能用之后我自己连续用了将近两个月也找了几位朋友帮忙测试。这里写一点真实感受以及我后续考虑扩展的方向给大家做个参考。5.1 真正帮我提高了多少效率我先说结论最明显的效率提升不在“答对了几道题”而在于它帮我建立了稳定的“学习反馈机制”。以前我的问题是看材料时觉得自己都会了实际做题才发现一堆盲区。现在自动出题模块每天根据我当天导入的资料生成题目做完直接进入错题本然后背诵卡会在第二天、第三天自动把相关知识点再拎出来让我复习。这个流程跑起来之后我明显感觉到知识点留存率高了不少隔一周再回看同一个章节熟悉感比之前强很多。本地运行带来的一个间接好处是我反而更愿意用它了。以前打开在线工具我总觉得像是在“借用”别人的服务心里有种无形负担怕打扰、怕留下记录、怕断线之后白忙。现在这个软件安安静静躺在自己的电脑里随时打开随时关我甚至觉得它更像一个“本地学习台灯”而不是“AI 云服务”。5.2 对于硬件配置的真实门槛很多人在网上问“本地 AI 到底要多高的配置”我的实际体验是如果愿意用 3B 级别模型一台 8 GB 内存的电脑就能流畅运行问答和出题功能如果追求 7B 模型的答案质量建议至少 16 GB 内存如果有独显更好但即使是核显也能跑只是速度慢一些。学习软件的互动节奏本来就是“问一个问题、读一段答案、想一想、再问下一个”所以每秒 8 到 15 个 token 的生成速度并不会让人抓狂。这一点真的不用被网上各种跑分党吓到。5.3 后续可以扩展的方向目前的版本已经覆盖了学习闭环的主要环节但我脑子里还有几个明确想做的方向顺便在这里抛出来如果有人愿意参与贡献那就太好了。第一个方向是语音问答。在现有问答模块上加语音输入和朗读功能让用户刷牙做饭的时候也能听知识点。技术上的难点不大需要注意语音识别也要本地化不然就破了自己“离线优先”的定位。第二个方向是题目质量的自适应控制。现在模型出题的水平受提示词影响比较大后续我想加入一个打分模块让模型对自己的题目先做一遍自评根据知识点覆盖度、难度匹配度、干扰项合理性三个维度打分低于阈值的题目自动返回重写。这本质上是一个“模型自评”的工程不需要额外大模型参与。第三个方向是导出与分享。虽然数据默认不出本地但我准备加入一个“知识包导出”功能把用户选定的资料切片、检索索引和练习记录打包成一个加密文件用户可以手动备份或者通过安全渠道传给同事、学生。这既保持了隐私边界又能让学习数据在不同设备之间流转。最后再分享一点我的体会这套软件从最初写给自己用的脚本到后来整理成开源项目中间最大的变化是我对“本地 AI”的理解。以前我总觉得本地模型是“低配版的 ChatGPT”但现在我更愿意把它看成是一个完全属于自己、可以自由改造的工具。数据在你手里代码在你手里你心里清楚它不会突然改变行为也不会有任何商业策略夹在里面。做学习工具尤其如此。学习本来就该是一个私人的、连续的、安静的过程。如果你也有类似的想法建议别再观望了动手做一个小工具跑起来让模型成为你书桌上的一部分。代码在项目仓库里随便拿去用有问题也欢迎一起来改。