from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker, AsyncSession from sqlalchemy import inspect, text from sqlalchemy.orm import DeclarativeBase from config import settings engine = create_async_engine(settings.DATABASE_URL, echo=settings.DEBUG, pool_size=10, max_overflow=20) async_session = async_sessionmaker(engine, class_=AsyncSession, expire_on_commit=False) class Base(DeclarativeBase): pass async def get_db(): async with async_session() as session: try: yield session finally: await session.close() async def init_db(): from models.template import Template from models.paragraph import Paragraph from models.ai_model import AiModel from models.document import Document from models.generation_log import GenerationLog from models.reference_file import ReferenceFile from models.template_block import TemplateBlock async with engine.begin() as conn: await conn.run_sync(Base.metadata.create_all) dialect_name = conn.dialect.name # template_blocks 新增列 block_columns = await conn.run_sync(lambda sync_conn: [column["name"] for column in inspect(sync_conn).get_columns("template_blocks")]) if "anchor_start_index" not in block_columns: await conn.execute(text("ALTER TABLE template_blocks ADD COLUMN anchor_start_index INT DEFAULT 0")) if "anchor_end_index" not in block_columns: await conn.execute(text("ALTER TABLE template_blocks ADD COLUMN anchor_end_index INT DEFAULT 0")) if "html_snippet" not in block_columns: await conn.execute(text("ALTER TABLE template_blocks ADD COLUMN html_snippet TEXT")) # generation_logs 新增 block_id log_columns = await conn.run_sync(lambda sync_conn: [column["name"] for column in inspect(sync_conn).get_columns("generation_logs")]) if "block_id" not in log_columns: await conn.execute(text("ALTER TABLE generation_logs ADD COLUMN block_id INT DEFAULT NULL")) await conn.execute(text("ALTER TABLE generation_logs MODIFY COLUMN paragraph_id INT DEFAULT NULL")) columns = await conn.run_sync(lambda sync_conn: [column["name"] for column in inspect(sync_conn).get_columns("ai_models")]) if "supports_streaming" not in columns: if dialect_name == "sqlite": await conn.execute(text("ALTER TABLE ai_models ADD COLUMN supports_streaming BOOLEAN DEFAULT 0")) else: await conn.execute(text("ALTER TABLE ai_models ADD COLUMN supports_streaming TINYINT(1) DEFAULT 0")) if "enable_reasoning" not in columns: if dialect_name == "sqlite": await conn.execute(text("ALTER TABLE ai_models ADD COLUMN enable_reasoning BOOLEAN DEFAULT 0")) else: await conn.execute(text("ALTER TABLE ai_models ADD COLUMN enable_reasoning TINYINT(1) DEFAULT 0")) document_columns = await conn.run_sync( lambda sync_conn: [column["name"] for column in inspect(sync_conn).get_columns("documents")] ) if "request_payload_json" not in document_columns: await conn.execute(text("ALTER TABLE documents ADD COLUMN request_payload_json TEXT")) paragraph_columns = await conn.run_sync( lambda sync_conn: [column["name"] for column in inspect(sync_conn).get_columns("paragraphs")] ) if "anchor_title" not in paragraph_columns: await conn.execute(text("ALTER TABLE paragraphs ADD COLUMN anchor_title VARCHAR(500) DEFAULT ''")) await conn.execute(text("UPDATE paragraphs SET anchor_title = title WHERE anchor_title = '' OR anchor_title IS NULL")) if "write_mode" not in paragraph_columns: await conn.execute(text("ALTER TABLE paragraphs ADD COLUMN write_mode VARCHAR(30) DEFAULT 'replace_section'"))