04_数据模型设计指南:SQLModel + pgvector
·
第一阶段:添加向量类型支持
因为我们要存储 AI 的"向量(Embedding)",需要先给 Python 环境装个补丁。请在 apps/api 目录下运行:
uv add pgvector
第二阶段:定义模型 (models.py)
在 apps/api 下新建一个文件 models.py。我们将定义用户(User)和文档(Document)这两个核心表。
from pgvector.sqlalchemy import Vector
from sqlmodel import Field, SQLModel, Relationship, Column
from typing import List, Optional
from datetime import datetime
# 1. 用户模型
class User(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
username: str = Field(index=True, unique=True)
email: str = Field(unique=True)
created_at: datetime = Field(default_factory=datetime.utcnow)
# 建立与文档的关联:一个用户可以拥有多份文档
documents: List["Document"] = Relationship(back_populates="owner")
# 2. 文档模型(知识库的核心)
class Document(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
title: str = Field(index=True)
content: str # 原始内容
# 2026 年标配:向量字段
# 1536 是常用的向量维度(例如 OpenAI 的 text-embedding-3-small)
embedding: Optional[List[float]] = Field(
sa_column=Column(Vector(1536))
)
user_id: Optional[int] = Field(default=None, foreign_key="user.id")
owner: Optional[User] = Relationship(back_populates="documents")
created_at: datetime = Field(default_factory=datetime.utcnow)
第三阶段:关键点解析
3.1 为什么文档表要有 embedding?
这是 RAG(检索增强生成) 的根基。
- 当你上传一篇文章时,AI 会将其转化为一串 1536 维的数字(向量)并存入此字段。
- 检索时,数据库会计算你问题的向量与这些数字的"余弦相似度",从而瞬间找到最相关的知识。
3.2 行级安全 (RLS) 的预留
虽然代码里还没写,但我们在模型中关联了 user_id。这在 2026 年的企业级开发中至关重要,它能确保:A 公司的员工绝对搜不到 B 公司的机密文档,实现物理级的数据隔离。
3.3 HNSW 索引预告
我们在 title 上加了 index=True,而对于 embedding 字段,我们之后会手动在数据库中创建 HNSW 索引。这是 2026 年处理千万级文档、保持毫秒级搜索性能的秘密武器。
第四阶段:同步到数据库
回到你的 main.py,确保它导入了这些模型,以便启动时自动建表:
# 在 main.py 顶部添加
from models import User, Document
# 确保在 lifespan 函数中调用了 init_db()
更新后的 main.py 完整内容如下:
from fastapi import FastAPI
from contextlib import asynccontextmanager
from database import init_db, engine
from sqlmodel import text
from models import User, Document # 导入模型,确保表被创建
@asynccontextmanager
async def lifespan(app: FastAPI):
# 启动时执行
with engine.connect() as conn:
# 激活向量扩展,这是 2026 年 RAG 系统的核心
conn.execute(text("CREATE EXTENSION IF NOT EXISTS vector;"))
conn.commit()
init_db() # 这会创建所有表,包括 User 和 Document
yield
# 关闭时执行(如果需要清理资源)
app = FastAPI(lifespan=lifespan)
@app.get("/")
async def root():
return {"message": "Hello from KnoSphere API!"}
@app.get("/health")
async def health():
return {"status": "healthy"}
# 可选的测试代码
# if __name__ == "__main__":
# import uvicorn
# uvicorn.run(app, host="0.0.0.0", port=8000)
注意:如果你想运行测试服务器,请确保已经安装了 uvicorn:
uv add uvicorn[standard]
检查点:KnoSphere 的骨架已成型
- User 表:可以存储用户信息和权限控制。
- Document 表:不仅能存文本,还能存 AI 向量。
- 关联关系:系统已经知道哪份知识属于哪个用户。
更多推荐




所有评论(0)