75 lines
3.6 KiB
Python
75 lines
3.6 KiB
Python
"""世谱(Lorebook / World Info)模型。
|
|
|
|
兼容酒馆 character_book 结构 + 魂镜扩展(scope / bound_entity_id)。
|
|
纯逻辑(匹配 / 预算 / 分组)在 app.modules.lorebook,本文件仅持久化载体。
|
|
"""
|
|
|
|
from datetime import datetime
|
|
|
|
from sqlalchemy import Boolean, DateTime, ForeignKey, Integer, String, Text
|
|
from sqlalchemy.orm import Mapped, mapped_column
|
|
|
|
from app.core.ids import new_lorebook_entry_id, new_lorebook_id
|
|
from app.core.time import utc_now
|
|
from app.db.base import Base
|
|
|
|
|
|
class Lorebook(Base):
|
|
"""一本世谱:条目集合 + 扫描 / 预算参数。
|
|
|
|
``character_id`` 为空表示 global 作用域(跨人物共享);非空时按人物隔离。
|
|
"""
|
|
|
|
__tablename__ = "lorebooks"
|
|
|
|
id: Mapped[str] = mapped_column(String(80), primary_key=True, default=new_lorebook_id)
|
|
character_id: Mapped[str | None] = mapped_column(
|
|
String(80), ForeignKey("characters.id"), index=True
|
|
)
|
|
name: Mapped[str] = mapped_column(String(200), nullable=False, default="")
|
|
description: Mapped[str] = mapped_column(Text, nullable=False, default="")
|
|
scan_depth: Mapped[int | None] = mapped_column(Integer)
|
|
token_budget: Mapped[int | None] = mapped_column(Integer)
|
|
recursive_scanning: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
|
|
scope: Mapped[str] = mapped_column(String(40), nullable=False, default="character", index=True)
|
|
status: Mapped[str] = mapped_column(String(40), nullable=False, default="active", index=True)
|
|
owner_scope: Mapped[str] = mapped_column(String(80), nullable=False, index=True)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utc_now)
|
|
updated_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True), default=utc_now, onupdate=utc_now
|
|
)
|
|
|
|
|
|
class LorebookEntry(Base):
|
|
"""单条世谱条目:keys 命中后注入 content。
|
|
|
|
``keys`` / ``secondary_keys`` 为字符串数组,落库存 JSON 文本(契约字典 §4)。
|
|
"""
|
|
|
|
__tablename__ = "lorebook_entries"
|
|
|
|
id: Mapped[str] = mapped_column(
|
|
String(80), primary_key=True, default=new_lorebook_entry_id
|
|
)
|
|
lorebook_id: Mapped[str] = mapped_column(
|
|
String(80), ForeignKey("lorebooks.id"), nullable=False, index=True
|
|
)
|
|
keys_json: Mapped[str] = mapped_column(Text, nullable=False, default="[]")
|
|
content: Mapped[str] = mapped_column(Text, nullable=False, default="")
|
|
secondary_keys_json: Mapped[str] = mapped_column(Text, nullable=False, default="[]")
|
|
constant: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
|
|
selective: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
|
|
enabled: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True)
|
|
case_sensitive: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
|
|
use_regex: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
|
|
position: Mapped[str] = mapped_column(String(40), nullable=False, default="after_char")
|
|
insertion_order: Mapped[int] = mapped_column(Integer, nullable=False, default=100)
|
|
priority: Mapped[int] = mapped_column(Integer, nullable=False, default=10)
|
|
comment: Mapped[str] = mapped_column(String(500), nullable=False, default="")
|
|
# 软引用河图世界实体(绑定触发);不加 FK,避免跨枢强耦合
|
|
bound_entity_id: Mapped[str | None] = mapped_column(String(80), index=True)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utc_now)
|
|
updated_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True), default=utc_now, onupdate=utc_now
|
|
)
|