为什么做这个
项目名 GameMind——《基于大语言模型与 RAG 知识库的游戏智能问答系统》。
选题动机来自一个很日常的烦恼:玩游戏遇到问题,想查点什么都费劲。攻略散落在贴吧、B 站、Wiki、官方公告等十几个地方;搜索引擎给的是网页不是答案;新手更惨,连「该搜什么」都不知道。通用大模型呢?一问三不知,还会一本正经地编角色技能。
所以思路很直接:RAG + 本地大模型——知识库保证回答有据可依,本地部署保证零成本、可离线、数据不出门。
系统能做什么
- 智能问答——「原神里雷电将军的技能怎么用?」直接给答案,附引用来源和检索过程
- 截图识别——丢一张游戏截图,多模态模型告诉你这是什么游戏、什么角色
- 知识库管理——上传 Markdown/PDF/Word,自动解析、切片、向量化入库
- 游戏推荐——接 RAWG API,输入喜欢的游戏推荐相似款并给理由
- RAG 检索可视化——重点创新,后面细说
内置原神、崩坏:星穹铁道、英雄联盟三个游戏的知识库起步,另从 Steam/RAWG 导入了 13 款游戏、28 个角色的结构化数据。
整体架构
四层结构,从上到下:
前端展示层 React 18 + Ant Design + Vite(聊天/知识库管理/游戏信息)后端服务层 FastAPI + LangGraph Agent(聊天/知识/游戏/用户四组 API)AI 引擎层 Ollama 本地推理 + RAG 管道(LangChain + FAISS)数据存储层 SQLite(关系数据)+ FAISS(向量)+ Neo4j(知识图谱)模型选型:qwen2.5:7b 管文本生成(中文能力对 7B 来说够惊喜),llava:13b 管图像理解,嵌入用中文优化模型。全部跑在 Ollama 上,拔掉网线系统照常工作。
LangGraph:把 Agent 画成一张图
这个项目让我第一次认真用了 LangGraph,体验比想象中好。Agent 的工作流就是一张显式的状态图:
classify_input(判断输入类型:text / image / mixed) │ ├─ text ──► rag_retrieve ──────┐ ├─ image ──► vision_analyze ────┤ └─ mixed ──► 两者都走 ──────────┤ ▼ generate_answer(综合上下文生成) ▼ format_output(格式化输出)分类节点简单到可爱,但把「用户发了什么」这个决策显式化之后,后面的每条路径都清晰可测:
def classify_input(state: AgentState) -> dict: has_text = bool(state.get("user_message", "").strip()) has_image = bool(state.get("image_path")) if has_text and has_image: input_type = "mixed" elif has_image: input_type = "image" else: input_type = "text" return {"input_type": input_type}每个节点只做一件事、只返回状态的增量更新,检索失败就置空上下文继续走——降级而不是崩溃,这个原则贯穿全项目。
RAG 管道与检索可视化
检索链路是标准的六步:提问 → 查询改写(提取关键词)→ FAISS 向量检索 → 结构化数据库查询 → 拼装上下文 → LLM 生成。
两处值得一提的设计:
混合检索。向量库负责「语义相关」,SQLite 负责「结构化精确」——问「雷电将军」时,向量库捞出技能攻略,结构化库捞出角色的属性、武器、定位数据,两路拼在一起喂给模型,回答的完整度明显好于单路。
检索过程可视化,这是系统的核心创新点。点「查看检索过程」,用户能看到完整链路:原始问题 → 改写后的查询 → 命中了哪些文档 → 相似度怎么排序 → 最终引用了哪几条。RAG 最大的问题是黑盒——用户不知道答案从哪来、可不可信。把检索过程摊开在桌面上,信任问题就解决了一半。答辩时老师对这个功能的兴趣也最大。
性能与真实代价
| 指标 | 实测数据 |
|---|---|
| 首次问答响应 | ~20 秒(模型冷启动) |
| 检索速度 | < 1 秒 |
| 知识库规模 | 5 个文档、65 个文本块 |
| 游戏数据 | 13 款游戏、28 个角色 |
这张表里最有信息量的是那个 20 秒——本地跑 7B 模型的真实代价。冷启动时模型加载 + 首次推理就是慢,这是全本地方案必须坦白的成本;换来的是之后每轮对话稳定输出、零 API 账单、以及数据永不离开这台电脑。工程就是取舍,把代价写在明处比假装它不存在更有说服力。
技术栈
| 层 | 技术 |
|---|---|
| 前端 | React 18 + Ant Design 5 + Vite + Axios |
| 后端 | FastAPI + SQLAlchemy(异步)+ SSE 流式 |
| Agent | LangGraph 状态图(分类/检索/视觉/生成四节点) |
| RAG | LangChain + FAISS + 中文嵌入模型 |
| 大模型 | Ollama:qwen2.5:7b(文本)+ llava:13b(视觉) |
| 存储 | SQLite + FAISS + Neo4j(知识图谱,可选) |
| 外部数据 | RAWG 游戏推荐 API |
做完这个项目,我对 RAG 的理解从「检索 + 生成」变成了「可信的知识服务」:检索质量决定下限,检索透明度决定用户敢不敢信,而本地化部署决定了这套东西能不能真正属于你。之前写的小面包文件助手是把 RAG 用在本地文件上,这次 GameMind 是用在垂直领域知识上——同一套思想,两种落地,越写越觉得 RAG 的本质其实是「给大模型装上可验证的记忆」。