Files
NovalRedot/backend/app/database.py
ROOG b39377e487
All checks were successful
Deploy Noval to K3s / deploy (push) Successful in 47s
新增文件管理与技能管理功能:
- **文件管理**:
  - 支持文件上传、解析和删除。
  - 限制支持格式(txt, md, docx, pdf),最大 10MB。
  - 提供前端上传区、文件列表及后端解析服务。

- **技能管理**:
  - 新增技能的创建、更新及删除功能。
  - 支持分配自定义提示词和工具权限。
  - 提供技能列表及分组工具选择交互界面。

同时调整相关 API 和前端组件,优化协作体验。
2026-03-22 23:50:14 +08:00

89 lines
4.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import json
import os
from pathlib import Path
from sqlalchemy import text
from sqlmodel import SQLModel, Session, create_engine, select
# 数据目录优先使用环境变量Docker 中设为 /app/data否则用 backend/data/
DATA_DIR = Path(os.environ.get("NOVAL_DATA_DIR", Path(__file__).resolve().parent.parent / "data"))
DATA_DIR.mkdir(exist_ok=True)
DATABASE_URL = f"sqlite:///{DATA_DIR / 'noval.db'}"
engine = create_engine(DATABASE_URL, echo=False)
def init_db() -> None:
SQLModel.metadata.create_all(engine)
_migrate_outline_parent_id()
_seed_builtin_skills()
def _migrate_outline_parent_id() -> None:
"""迁移:为 outline 表添加 parent_id 列(如果尚不存在)"""
with Session(engine) as session:
# 检查 outline 表是否存在 parent_id 列
result = session.exec(text("PRAGMA table_info(outline)"))
columns = [row[1] for row in result]
if "parent_id" not in columns:
session.exec(text("ALTER TABLE outline ADD COLUMN parent_id INTEGER REFERENCES outline(id)"))
session.exec(text("CREATE INDEX IF NOT EXISTS ix_outline_parent_id ON outline(parent_id)"))
session.commit()
def _seed_builtin_skills() -> None:
"""初始化预置 Skill仅首次运行时插入"""
from .models import Skill # 延迟导入避免循环
with Session(engine) as session:
existing = session.exec(select(Skill).where(Skill.is_builtin == True)).first() # noqa: E712
if existing:
return # 已初始化过
builtin_skills = [
Skill(
name="通用写作助手",
description="全能写作助手,可使用所有工具",
system_prompt="你是一个专业的小说写作助手,擅长构思情节、塑造角色、打磨文笔。请根据用户需求提供创作建议,必要时主动使用工具查看和操作小说数据。",
allowed_tools="[]",
is_builtin=True,
),
Skill(
name="大纲规划师",
description="构建清晰的故事骨架,规划情节节点",
system_prompt="你是大纲规划专家。请帮助用户构建清晰的故事骨架,包括起承转合、情节节点和分章结构。分析现有大纲时请关注因果逻辑、节奏控制和悬念布置。在操作大纲时,注意保持节点间的逻辑连贯性。",
allowed_tools=json.dumps(["get_novel_info", "list_outlines", "create_outline", "update_outline", "delete_outline", "reorder_outlines"]),
is_builtin=True,
),
Skill(
name="角色塑造师",
description="设计立体、有深度的角色",
system_prompt="你是角色塑造专家。请帮助用户设计立体、有深度的角色,包括外貌、性格、动机、成长弧线和人物关系。注意角色间的化学反应和戏剧张力,确保每个角色都有独特的声音和行为逻辑。",
allowed_tools=json.dumps(["get_novel_info", "list_characters", "create_character", "update_character", "delete_character"]),
is_builtin=True,
),
Skill(
name="世界观架构师",
description="构建完整自洽的虚构世界",
system_prompt="你是世界观构建专家。请帮助用户设计完整自洽的虚构世界,包括地理、历史、政治、经济、魔法或科技体系等。确保设定内部逻辑一致,并与故事主线相辅相成。",
allowed_tools=json.dumps(["get_novel_info", "get_world_setting", "save_world_setting", "list_outlines", "list_characters"]),
is_builtin=True,
),
Skill(
name="文稿分析师",
description="分析上传的小说或剧本文件",
system_prompt="你是文稿分析专家。请仔细阅读用户上传的文件,提取关键信息,分析文风、角色、情节结构,并提供改进建议。分析时可以分段读取大文件,注意把握整体脉络。",
allowed_tools=json.dumps(["get_novel_info", "list_files", "read_file", "list_outlines", "list_characters", "list_chapters"]),
is_builtin=True,
),
]
for skill in builtin_skills:
session.add(skill)
session.commit()
def get_session():
with Session(engine) as session:
yield session