91 lines
3.3 KiB
Python
91 lines
3.3 KiB
Python
"""
|
||
ORM 模型定义
|
||
|
||
SQLite 数据库模型,使用 Text 存储 JSON 格式的向量。
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import json
|
||
from datetime import datetime
|
||
from typing import Any, Dict
|
||
|
||
from sqlalchemy import DateTime, Float, Integer, String, Text, func
|
||
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
|
||
|
||
|
||
class Base(DeclarativeBase):
|
||
"""所有 ORM 模型的基类"""
|
||
pass
|
||
|
||
|
||
class TimestampMixin:
|
||
"""时间戳 Mixin"""
|
||
|
||
created_at: Mapped[datetime] = mapped_column(
|
||
DateTime, default=func.now(), comment="创建时间"
|
||
)
|
||
updated_at: Mapped[datetime] = mapped_column(
|
||
DateTime, default=func.now(), onupdate=func.now(), comment="更新时间"
|
||
)
|
||
|
||
|
||
class KnowledgePage(Base, TimestampMixin):
|
||
"""知识页面"""
|
||
__tablename__ = "knowledge_pages"
|
||
|
||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||
title: Mapped[str] = mapped_column(String(500), nullable=False, comment="页面标题")
|
||
content: Mapped[str] = mapped_column(Text, nullable=False, comment="页面内容")
|
||
source: Mapped[str | None] = mapped_column(String(200), nullable=True, comment="来源文件名")
|
||
page_number: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="原文件页码")
|
||
# 向量嵌入(JSON 格式存储)
|
||
embedding: Mapped[str | None] = mapped_column(Text, nullable=True, comment="向量嵌入(JSON)")
|
||
|
||
@property
|
||
def embedding_vector(self) -> list[float] | None:
|
||
if self.embedding is None:
|
||
return None
|
||
return json.loads(self.embedding)
|
||
|
||
@embedding_vector.setter
|
||
def embedding_vector(self, value: list[float] | None):
|
||
self.embedding = json.dumps(value) if value else None
|
||
|
||
|
||
class OCRImage(Base, TimestampMixin):
|
||
"""OCR 图片记录"""
|
||
__tablename__ = "ocr_images"
|
||
|
||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||
file_path: Mapped[str] = mapped_column(String(500), nullable=False, comment="图片文件路径")
|
||
original_filename: Mapped[str | None] = mapped_column(String(200), nullable=True, comment="原始文件名")
|
||
ocr_text: Mapped[str | None] = mapped_column(Text, nullable=True, comment="OCR 识别文本")
|
||
confidence: Mapped[float | None] = mapped_column(Float, nullable=True, comment="OCR 置信度")
|
||
provider: Mapped[str | None] = mapped_column(String(50), nullable=True, comment="OCR 提供商")
|
||
status: Mapped[str] = mapped_column(
|
||
String(20), default="pending", comment="状态: pending/processing/completed/failed"
|
||
)
|
||
blocks: Mapped[str | None] = mapped_column(Text, nullable=True, comment="OCR 文本块(JSON)")
|
||
|
||
@property
|
||
def blocks_list(self) -> list[dict]:
|
||
if self.blocks is None:
|
||
return []
|
||
return json.loads(self.blocks)
|
||
|
||
@blocks_list.setter
|
||
def blocks_list(self, value: list[dict]):
|
||
self.blocks = json.dumps(value) if value else None
|
||
|
||
|
||
class WebsiteSettings(Base):
|
||
"""网站设置(单例)"""
|
||
__tablename__ = "website_settings"
|
||
|
||
key: Mapped[str] = mapped_column(String(100), primary_key=True, comment="设置键")
|
||
value: Mapped[str | None] = mapped_column(Text, nullable=True, comment="设置值(JSON)")
|
||
updated_at: Mapped[datetime] = mapped_column(
|
||
DateTime, default=func.now(), onupdate=func.now(), comment="更新时间"
|
||
)
|