完整项目:手把手做「资料管家」
把这门课学的全串起来——从 0 做一个记得你、读得懂你资料的助手
攒了一整门课的本事,今天来真的:从 0 手把手做一个完整、能用的项目——「资料管家」。
你把笔记、文档喂给它,它就能:记得你刚问过什么、基于你的资料回答、还告诉你依据出自哪段。这是把 RAG(a2.3)+ 记忆(a2.2)+ 评估(a4.2)+ 上线(a4.3)全部串起来的一次真刀真枪。做完它,你就真正会造智能体了。
先按"四大件"设计(a0.3)
动手前先想清楚它由什么组成——这是老练的习惯:
🔧 手把手:一份完整可运行的「资料管家」
下面整段 复制即可运行(本地中文嵌入,免 VPN)。它把 RAG + 记忆 + 人设合在一起:
# pip install sentence-transformers openai
from sentence_transformers import SentenceTransformer, util
from openai import OpenAI
embedder = SentenceTransformer("BAAI/bge-small-zh-v1.5")
client = OpenAI(api_key="你的KEY", base_url="https://api.deepseek.com")
# ① 你的资料(真实项目从文件读,这里手写几段演示)
DOCS = [
"项目一键部署:bash deploy.sh;部署前必须先备份数据库。",
"技术栈:Next.js + Prisma + MySQL,部署在阿里云。",
"课程分 5 章 + 进阶篇,从'什么是智能体'讲到'训练智能体'。",
]
DOC_VECS = embedder.encode(DOCS, normalize_embeddings=True) # ② 入库:算嵌入
PERSONA = "你是「资料管家」。只根据给你的资料回答,并指出依据;资料里没有就说不知道,绝不编。"
history = [] # 对话记忆
def retrieve(q, k=2): # ③ 检索:找最相关的几段
qv = embedder.encode(q, normalize_embeddings=True)
top = util.cos_sim(qv, DOC_VECS)[0].argsort(descending=True)[:k]
return "\n".join(f"- {DOCS[i]}" for i in top)
def ask(question):
context = retrieve(question)
messages = ([{"role": "system", "content": PERSONA}]
+ history[-4:] # ④ 带上最近的对话记忆
+ [{"role": "user", "content": f"资料:\n{context}\n\n问题:{question}"}])
answer = client.chat.completions.create(
model="deepseek-chat", messages=messages).choices[0].message.content
history.extend([{"role": , : question},
{: , : answer}])
answer
(, ask())
(, ask())
跑一遍,你会看到:Q1 它从资料里查出 bash deploy.sh;Q2 你只说"那",它靠记忆知道在说部署、靠检索答出"先备份数据库"——记忆 + RAG 合体,一个真正"懂你"的助手就成了。
让它吃真实文件:读取 + 切块
上面的 DOCS 是手写的几段。真实项目里资料在文件里,而且一篇长文档不能整篇塞——要切块(chunking):切太大检索不准、塞不下,切太小又丢上下文。一个够用的做法是按长度切、块之间留点重叠:
import os, glob
def load_and_chunk(folder="docs", size=300, overlap=50):
"""读 folder 下所有 .txt,按字数切块,块间重叠 overlap 字保留上下文。"""
chunks = []
for path in glob.glob(os.path.join(folder, "*.txt")):
text = open(path, encoding="utf-8").read()
for i in range(0, len(text), size - overlap): # 步长=块长-重叠
piece = text[i:i + size].strip()
if piece:
chunks.append(piece)
return chunks
# 用它替换手写的 DOCS(确保 docs/ 文件夹里有 .txt 资料):
# DOCS = load_and_chunk("docs")
# DOC_VECS = embedder.encode(DOCS, normalize_embeddings=True)
切块是 RAG 效果最大的旋钮之一:中文资料
size先试 300–500 字、overlap50 左右,按检索效果再调。
再走完最后两步:评估 + 上线
评估(a4.2):列几道只有你资料里才有答案的题,跑一遍看通过率——
tests = [("一键部署命令?", "deploy.sh"), ("用什么数据库?", "MySQL")]
passed = sum(t[1].lower() in ask(t[0]).lower() for t in tests)
print(f"通过率:{passed}/{len(tests)}")
上线(a4.3):把 ask() 包成一个 HTTP 接口,加上最简配额(防被刷爆账单),就能发给别人用了——下面这段配合上面的代码可直接跑:
# pip install "fastapi>=0.110" "uvicorn>=0.27"
from fastapi import FastAPI, HTTPException
from collections import defaultdict
app = FastAPI()
quota = defaultdict(int) # 极简内存配额:真实项目用 Redis/数据库按用户计
@app.post("/ask")
def ask_api(question: str, user: str = "guest"):
if quota[user] >= 20: # ← 每用户每进程最多 20 次,挡住恶意刷量
raise HTTPException(429, "今日额度已用完")
quota[user] += 1
return {"answer": ask(question)}
# 启动:uvicorn 文件名:app --reload,然后 POST /ask?question=一键部署命令
不想写后端?把这些资料传进扣子知识库,点几下发布,效果一样。但配额这一关无论哪条路都不能省——公开的智能体不设防,等于让人刷你的钱(呼应 a4.3 / e6)。
- 隐私:敏感资料(身份证、密钥、商业机密)别随手喂给第三方平台。
- 出处:让它给依据,你才能一眼看出是"有据"还是"瞎编"(尤其涉及钱/合同)。
- 评估:上线前用测试集跑一遍;别"感觉行"就发出去。
这三件,正是"做出来"和"做可靠"的差距。
我想基于这套「RAG + 记忆 + 人设」做一个『___ 助手』(我来填,如:法规问答 / 产品客服 / 个人笔记)。请帮我:① 该喂哪些资料、怎么切块 ② 人设(PERSONA)怎么写 ③ 3 道评估测试题 ④ 上线和隐私注意事项。
🏆 你做出了一个完整、能用的智能体——记得你、读你的资料、有据可查、还能评估上线。这已经是不少付费产品的核心,而你亲手从 0 串了起来。
资料管家偏"问答"。下一个项目换个味道:做一个多工具、多步骤的「旅行助手」——查天气、查票价、算预算、给建议,用上 LangGraph 把这些工具自动编排起来。再练一种典型的智能体形态。
