feat: 建立知识版本与检索追踪数据模型
This commit is contained in:
@@ -0,0 +1,319 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.dialects import mysql
|
||||
|
||||
revision = "0007_knowledge_agent_rebuild"
|
||||
down_revision = "0006_expand_ai_request_log_text"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
for column in [
|
||||
sa.Column("source_title", sa.String(255), nullable=True),
|
||||
sa.Column("knowledge_type", sa.String(30), nullable=False, server_default="general"),
|
||||
sa.Column("review_mode", sa.String(30), nullable=False, server_default="manual"),
|
||||
sa.Column("lifecycle_status", sa.String(30), nullable=False, server_default="active"),
|
||||
sa.Column("source_status", sa.String(30), nullable=False, server_default="normal"),
|
||||
sa.Column("source_error", mysql.MEDIUMTEXT(), nullable=True),
|
||||
sa.Column("manifest_confirmed", sa.Integer(), nullable=False, server_default="0"),
|
||||
sa.Column("current_version_id", sa.BigInteger(), nullable=True),
|
||||
sa.Column("pending_version_id", sa.BigInteger(), nullable=True),
|
||||
sa.Column("last_synced_at", sa.DateTime(), nullable=True),
|
||||
sa.Column("last_published_at", sa.DateTime(), nullable=True),
|
||||
sa.Column("migration_status", sa.String(30), nullable=False, server_default="pending"),
|
||||
]:
|
||||
op.add_column("sys_knowledge", column)
|
||||
|
||||
op.create_table(
|
||||
"sys_knowledge_source_snapshot",
|
||||
sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
|
||||
sa.Column("knowledge_id", sa.BigInteger(), nullable=False),
|
||||
sa.Column("sync_job_id", sa.BigInteger(), nullable=True),
|
||||
sa.Column("source_title", sa.String(255), nullable=False),
|
||||
sa.Column("source_content", mysql.LONGTEXT(), nullable=False),
|
||||
sa.Column("content_hash", sa.String(64), nullable=False),
|
||||
sa.Column("source_identifier", sa.String(255), nullable=False),
|
||||
sa.Column("fetched_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False),
|
||||
sa.Column("created_by", sa.BigInteger(), nullable=True),
|
||||
sa.ForeignKeyConstraint(["knowledge_id"], ["sys_knowledge.id"]),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
)
|
||||
_indexes("sys_knowledge_source_snapshot", "knowledge_id", "sync_job_id", "content_hash")
|
||||
|
||||
op.create_table(
|
||||
"sys_knowledge_version",
|
||||
sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
|
||||
sa.Column("knowledge_id", sa.BigInteger(), nullable=False),
|
||||
sa.Column("snapshot_id", sa.BigInteger(), nullable=False),
|
||||
sa.Column("version_no", sa.Integer(), nullable=False),
|
||||
sa.Column("status", sa.String(30), nullable=False),
|
||||
sa.Column("quality_status", sa.String(30), nullable=False, server_default="pending"),
|
||||
sa.Column("change_summary", mysql.MEDIUMTEXT(), nullable=True),
|
||||
sa.Column("quality_report", mysql.MEDIUMTEXT(), nullable=True),
|
||||
sa.Column("processing_rule_version", sa.String(50), nullable=False),
|
||||
sa.Column("generation_model", sa.String(100), nullable=True),
|
||||
sa.Column("created_by", sa.BigInteger(), nullable=True),
|
||||
sa.Column("created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False),
|
||||
sa.Column("published_by", sa.BigInteger(), nullable=True),
|
||||
sa.Column("published_at", sa.DateTime(), nullable=True),
|
||||
sa.ForeignKeyConstraint(["knowledge_id"], ["sys_knowledge.id"]),
|
||||
sa.ForeignKeyConstraint(["snapshot_id"], ["sys_knowledge_source_snapshot.id"]),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
sa.UniqueConstraint("knowledge_id", "version_no", name="uq_kb_version_no"),
|
||||
)
|
||||
_indexes("sys_knowledge_version", "knowledge_id", "status")
|
||||
|
||||
op.create_table(
|
||||
"sys_knowledge_manifest",
|
||||
sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
|
||||
sa.Column("knowledge_id", sa.BigInteger(), nullable=False),
|
||||
sa.Column("version_id", sa.BigInteger(), nullable=False),
|
||||
sa.Column("purpose", mysql.MEDIUMTEXT(), nullable=False),
|
||||
sa.Column("applicable_questions", mysql.MEDIUMTEXT(), nullable=False),
|
||||
sa.Column("inapplicable_questions", mysql.MEDIUMTEXT(), nullable=False),
|
||||
sa.Column("core_topics", mysql.MEDIUMTEXT(), nullable=False),
|
||||
sa.Column("entities", mysql.MEDIUMTEXT(), nullable=True),
|
||||
sa.Column("boundaries", mysql.MEDIUMTEXT(), nullable=True),
|
||||
sa.Column("content_hash", sa.String(64), nullable=False),
|
||||
sa.Column("change_level", sa.String(20), nullable=False, server_default="major"),
|
||||
sa.Column("confirmed", sa.Integer(), nullable=False, server_default="0"),
|
||||
sa.Column("confirmed_by", sa.BigInteger(), nullable=True),
|
||||
sa.Column("confirmed_at", sa.DateTime(), nullable=True),
|
||||
sa.ForeignKeyConstraint(["knowledge_id"], ["sys_knowledge.id"]),
|
||||
sa.ForeignKeyConstraint(["version_id"], ["sys_knowledge_version.id"]),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
)
|
||||
_indexes("sys_knowledge_manifest", "knowledge_id", "version_id")
|
||||
|
||||
op.create_table(
|
||||
"sys_knowledge_section",
|
||||
sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
|
||||
sa.Column("knowledge_id", sa.BigInteger(), nullable=False),
|
||||
sa.Column("version_id", sa.BigInteger(), nullable=False),
|
||||
sa.Column("section_key", sa.String(64), nullable=False),
|
||||
sa.Column("title", sa.String(255), nullable=False),
|
||||
sa.Column("content", mysql.LONGTEXT(), nullable=False),
|
||||
sa.Column("source_start", sa.Integer(), nullable=False),
|
||||
sa.Column("source_end", sa.Integer(), nullable=False),
|
||||
sa.Column("sort_order", sa.Integer(), nullable=False),
|
||||
sa.Column("content_hash", sa.String(64), nullable=False),
|
||||
sa.ForeignKeyConstraint(["knowledge_id"], ["sys_knowledge.id"]),
|
||||
sa.ForeignKeyConstraint(["version_id"], ["sys_knowledge_version.id"]),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
)
|
||||
_indexes("sys_knowledge_section", "knowledge_id", "version_id")
|
||||
|
||||
op.create_table(
|
||||
"sys_knowledge_chunk",
|
||||
sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
|
||||
sa.Column("knowledge_id", sa.BigInteger(), nullable=False),
|
||||
sa.Column("version_id", sa.BigInteger(), nullable=False),
|
||||
sa.Column("section_id", sa.BigInteger(), nullable=False),
|
||||
sa.Column("title", sa.String(255), nullable=False),
|
||||
sa.Column("content", mysql.MEDIUMTEXT(), nullable=False),
|
||||
sa.Column("normalized_text", mysql.MEDIUMTEXT(), nullable=False),
|
||||
sa.Column("keywords", mysql.MEDIUMTEXT(), nullable=True),
|
||||
sa.Column("synonyms", mysql.MEDIUMTEXT(), nullable=True),
|
||||
sa.Column("source_start", sa.Integer(), nullable=False),
|
||||
sa.Column("source_end", sa.Integer(), nullable=False),
|
||||
sa.Column("sort_order", sa.Integer(), nullable=False),
|
||||
sa.Column("content_hash", sa.String(64), nullable=False),
|
||||
sa.ForeignKeyConstraint(["knowledge_id"], ["sys_knowledge.id"]),
|
||||
sa.ForeignKeyConstraint(["version_id"], ["sys_knowledge_version.id"]),
|
||||
sa.ForeignKeyConstraint(["section_id"], ["sys_knowledge_section.id"]),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
)
|
||||
_indexes("sys_knowledge_chunk", "knowledge_id", "version_id", "section_id")
|
||||
|
||||
op.create_table(
|
||||
"sys_knowledge_card",
|
||||
sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
|
||||
sa.Column("knowledge_id", sa.BigInteger(), nullable=False),
|
||||
sa.Column("version_id", sa.BigInteger(), nullable=False),
|
||||
sa.Column("section_id", sa.BigInteger(), nullable=False),
|
||||
sa.Column("title", sa.String(255), nullable=False),
|
||||
sa.Column("summary", mysql.MEDIUMTEXT(), nullable=False),
|
||||
sa.Column("core_conclusion", mysql.MEDIUMTEXT(), nullable=False),
|
||||
sa.Column("applicable_questions", mysql.MEDIUMTEXT(), nullable=False),
|
||||
sa.Column("inapplicable_questions", mysql.MEDIUMTEXT(), nullable=False),
|
||||
sa.Column("keywords", mysql.MEDIUMTEXT(), nullable=False),
|
||||
sa.Column("synonyms", mysql.MEDIUMTEXT(), nullable=True),
|
||||
sa.Column("entities", mysql.MEDIUMTEXT(), nullable=True),
|
||||
sa.Column("risk_level", sa.String(20), nullable=False, server_default="normal"),
|
||||
sa.Column("source_range", sa.String(100), nullable=False),
|
||||
sa.Column("content_hash", sa.String(64), nullable=False),
|
||||
sa.Column("generation_model", sa.String(100), nullable=True),
|
||||
sa.Column("generation_rule_version", sa.String(50), nullable=False),
|
||||
sa.Column("review_status", sa.String(20), nullable=False, server_default="pending"),
|
||||
sa.ForeignKeyConstraint(["knowledge_id"], ["sys_knowledge.id"]),
|
||||
sa.ForeignKeyConstraint(["version_id"], ["sys_knowledge_version.id"]),
|
||||
sa.ForeignKeyConstraint(["section_id"], ["sys_knowledge_section.id"]),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
)
|
||||
_indexes("sys_knowledge_card", "knowledge_id", "version_id", "section_id")
|
||||
|
||||
_create_job_and_log_tables()
|
||||
|
||||
|
||||
def _create_job_and_log_tables() -> None:
|
||||
op.create_table(
|
||||
"sys_knowledge_sync_job",
|
||||
sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
|
||||
sa.Column("knowledge_id", sa.BigInteger(), nullable=False),
|
||||
sa.Column("mode", sa.String(30), nullable=False),
|
||||
sa.Column("status", sa.String(30), nullable=False),
|
||||
sa.Column("stage", sa.String(50), nullable=False),
|
||||
sa.Column("progress", sa.Integer(), nullable=False, server_default="0"),
|
||||
sa.Column("source_error", mysql.MEDIUMTEXT(), nullable=True),
|
||||
sa.Column("result_summary", mysql.MEDIUMTEXT(), nullable=True),
|
||||
sa.Column("requested_by", sa.BigInteger(), nullable=False),
|
||||
sa.Column("created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False),
|
||||
sa.Column("started_at", sa.DateTime(), nullable=True),
|
||||
sa.Column("finished_at", sa.DateTime(), nullable=True),
|
||||
sa.ForeignKeyConstraint(["knowledge_id"], ["sys_knowledge.id"]),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
)
|
||||
_indexes("sys_knowledge_sync_job", "knowledge_id", "status")
|
||||
|
||||
op.create_table(
|
||||
"sys_knowledge_review_record",
|
||||
sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
|
||||
sa.Column("knowledge_id", sa.BigInteger(), nullable=False),
|
||||
sa.Column("version_id", sa.BigInteger(), nullable=False),
|
||||
sa.Column("card_id", sa.BigInteger(), nullable=True),
|
||||
sa.Column("action", sa.String(30), nullable=False),
|
||||
sa.Column("reason", mysql.MEDIUMTEXT(), nullable=True),
|
||||
sa.Column("reviewed_by", sa.BigInteger(), nullable=False),
|
||||
sa.Column("created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False),
|
||||
sa.ForeignKeyConstraint(["knowledge_id"], ["sys_knowledge.id"]),
|
||||
sa.ForeignKeyConstraint(["version_id"], ["sys_knowledge_version.id"]),
|
||||
sa.ForeignKeyConstraint(["card_id"], ["sys_knowledge_card.id"]),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
)
|
||||
_indexes("sys_knowledge_review_record", "knowledge_id", "version_id")
|
||||
|
||||
op.create_table(
|
||||
"sys_knowledge_publish_log",
|
||||
sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
|
||||
sa.Column("knowledge_id", sa.BigInteger(), nullable=False),
|
||||
sa.Column("from_version_id", sa.BigInteger(), nullable=True),
|
||||
sa.Column("to_version_id", sa.BigInteger(), nullable=True),
|
||||
sa.Column("action", sa.String(30), nullable=False),
|
||||
sa.Column("keep_open", sa.Integer(), nullable=False, server_default="0"),
|
||||
sa.Column("detail_json", mysql.MEDIUMTEXT(), nullable=True),
|
||||
sa.Column("operated_by", sa.BigInteger(), nullable=False),
|
||||
sa.Column("created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False),
|
||||
sa.ForeignKeyConstraint(["knowledge_id"], ["sys_knowledge.id"]),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
)
|
||||
_indexes("sys_knowledge_publish_log", "knowledge_id")
|
||||
|
||||
op.create_table(
|
||||
"sys_knowledge_retrieval_log",
|
||||
sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
|
||||
sa.Column("session_id", sa.BigInteger(), nullable=True),
|
||||
sa.Column("message_id", sa.BigInteger(), nullable=True),
|
||||
sa.Column("user_id", sa.BigInteger(), nullable=True),
|
||||
sa.Column("question", mysql.MEDIUMTEXT(), nullable=False),
|
||||
sa.Column("catalog_snapshot", mysql.LONGTEXT(), nullable=False),
|
||||
sa.Column("catalog_hash", sa.String(64), nullable=False),
|
||||
sa.Column("safety_rule_version", sa.String(50), nullable=False),
|
||||
sa.Column("knowledge_called", sa.Integer(), nullable=False, server_default="0"),
|
||||
sa.Column("selected_knowledge_ids", sa.String(500), nullable=True),
|
||||
sa.Column("query_terms", mysql.MEDIUMTEXT(), nullable=True),
|
||||
sa.Column("tool_trace", mysql.LONGTEXT(), nullable=True),
|
||||
sa.Column("final_section_ids", sa.String(500), nullable=True),
|
||||
sa.Column("discarded_conflicts", mysql.MEDIUMTEXT(), nullable=True),
|
||||
sa.Column("final_answer", mysql.LONGTEXT(), nullable=True),
|
||||
sa.Column("status", sa.String(20), nullable=False),
|
||||
sa.Column("tool_cost_ms", sa.Integer(), nullable=True),
|
||||
sa.Column("total_cost_ms", sa.Integer(), nullable=True),
|
||||
sa.Column("error_message", mysql.MEDIUMTEXT(), nullable=True),
|
||||
sa.Column("attention_created", sa.Integer(), nullable=False, server_default="0"),
|
||||
sa.Column("created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
)
|
||||
_indexes("sys_knowledge_retrieval_log", "session_id", "message_id", "user_id")
|
||||
|
||||
op.create_table(
|
||||
"sys_knowledge_retrieval_candidate",
|
||||
sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
|
||||
sa.Column("retrieval_log_id", sa.BigInteger(), nullable=False),
|
||||
sa.Column("knowledge_id", sa.BigInteger(), nullable=False),
|
||||
sa.Column("version_id", sa.BigInteger(), nullable=False),
|
||||
sa.Column("chunk_id", sa.BigInteger(), nullable=False),
|
||||
sa.Column("section_id", sa.BigInteger(), nullable=False),
|
||||
sa.Column("lexical_score", sa.String(30), nullable=False),
|
||||
sa.Column("rerank_score", sa.String(30), nullable=True),
|
||||
sa.Column("selected", sa.Integer(), nullable=False, server_default="0"),
|
||||
sa.Column("discard_reason", sa.String(255), nullable=True),
|
||||
sa.ForeignKeyConstraint(["retrieval_log_id"], ["sys_knowledge_retrieval_log.id"]),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
)
|
||||
_indexes("sys_knowledge_retrieval_candidate", "retrieval_log_id", "knowledge_id", "version_id")
|
||||
|
||||
op.create_table(
|
||||
"sys_human_attention_record",
|
||||
sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
|
||||
sa.Column("session_id", sa.BigInteger(), nullable=False),
|
||||
sa.Column("message_id", sa.BigInteger(), nullable=False),
|
||||
sa.Column("user_id", sa.BigInteger(), nullable=False),
|
||||
sa.Column("trigger_message", mysql.MEDIUMTEXT(), nullable=False),
|
||||
sa.Column("problem_summary", mysql.MEDIUMTEXT(), nullable=False),
|
||||
sa.Column("trigger_reason", mysql.MEDIUMTEXT(), nullable=False),
|
||||
sa.Column("priority", sa.String(20), nullable=False),
|
||||
sa.Column("status", sa.String(20), nullable=False, server_default="pending"),
|
||||
sa.Column("handler_id", sa.BigInteger(), nullable=True),
|
||||
sa.Column("handler_note", mysql.MEDIUMTEXT(), nullable=True),
|
||||
sa.Column("created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False),
|
||||
sa.Column("updated_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
)
|
||||
_indexes("sys_human_attention_record", "session_id", "message_id", "user_id", "priority", "status")
|
||||
|
||||
op.create_table(
|
||||
"sys_human_attention_history",
|
||||
sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
|
||||
sa.Column("attention_id", sa.BigInteger(), nullable=False),
|
||||
sa.Column("from_status", sa.String(20), nullable=True),
|
||||
sa.Column("to_status", sa.String(20), nullable=False),
|
||||
sa.Column("note", mysql.MEDIUMTEXT(), nullable=True),
|
||||
sa.Column("operated_by", sa.BigInteger(), nullable=False),
|
||||
sa.Column("created_at", sa.DateTime(), server_default=sa.text("now()"), nullable=False),
|
||||
sa.ForeignKeyConstraint(["attention_id"], ["sys_human_attention_record.id"]),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
)
|
||||
_indexes("sys_human_attention_history", "attention_id")
|
||||
|
||||
|
||||
def _indexes(table: str, *columns: str) -> None:
|
||||
for column in columns:
|
||||
op.create_index(f"ix_{table}_{column}", table, [column])
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
for table in [
|
||||
"sys_human_attention_history",
|
||||
"sys_human_attention_record",
|
||||
"sys_knowledge_retrieval_candidate",
|
||||
"sys_knowledge_retrieval_log",
|
||||
"sys_knowledge_publish_log",
|
||||
"sys_knowledge_review_record",
|
||||
"sys_knowledge_sync_job",
|
||||
"sys_knowledge_card",
|
||||
"sys_knowledge_chunk",
|
||||
"sys_knowledge_section",
|
||||
"sys_knowledge_manifest",
|
||||
"sys_knowledge_version",
|
||||
"sys_knowledge_source_snapshot",
|
||||
]:
|
||||
op.drop_table(table)
|
||||
for column in [
|
||||
"migration_status", "last_published_at", "last_synced_at", "pending_version_id",
|
||||
"current_version_id", "manifest_confirmed", "source_error", "source_status",
|
||||
"lifecycle_status", "review_mode", "knowledge_type", "source_title",
|
||||
]:
|
||||
op.drop_column("sys_knowledge", column)
|
||||
Reference in New Issue
Block a user