Files
awoooi/apps/api/src/models/knowledge.py
Your Name d7f56351f2
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
Code Review / ai-code-review (push) Has been cancelled
CD Pipeline / tests (push) Failing after 14m8s
Type Sync Check / check-type-sync (push) Successful in 42s
CD Pipeline / build-and-deploy (push) Has been cancelled
CD Pipeline / post-deploy-checks (push) Has been cancelled
fix(recovery): reopen controlled automation after failclosed regression
2026-06-28 16:01:40 +08:00

130 lines
4.6 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.
"""
Knowledge Base Models
=====================
Phase KB-1: 知識庫資料模型
兩層架構:
- KnowledgeEntry: 知識條目 (incident_case / runbook / best_practice / postmortem)
- Playbook: 獨立系統,透過 related_playbook_id 關聯
建立時間: 2026-04-02 (台北時區)
建立者: Claude Code (Knowledge Base Phase 1)
遵循 leWOOOgo 積木化原則:
- Pydantic BaseModel 定義
- PostgreSQL Episodic Memory
"""
from datetime import datetime
from enum import Enum
from pydantic import BaseModel, Field
from src.utils.timezone import now_taipei
# =============================================================================
# Enums
# =============================================================================
class EntryType(str, Enum):
"""知識條目類型"""
INCIDENT_CASE = "incident_case" # AI 從 Incident 萃取的案例分析
RUNBOOK = "runbook" # 手動建立的操作手冊
BEST_PRACTICE = "best_practice" # 最佳實踐文章
POSTMORTEM = "postmortem" # 事後分析報告
# 2026-04-04 ogt: Phase 25 P1 — Knowledge Auto-Harvesting 新增類型
AUTO_RUNBOOK = "auto_runbook" # Nemotron 自動生成的 RunbookDRAFT 待 AI 受控複核)
ANTI_PATTERN = "anti_pattern" # 修復失敗案例(直接 PUBLISHED阻斷後續重蹈覆轍
class EntrySource(str, Enum):
"""知識來源"""
AI_EXTRACTED = "ai_extracted" # AI 自動萃取
HUMAN = "human" # 人工建立
class EntryStatus(str, Enum):
"""知識條目狀態"""
DRAFT = "draft" # 草稿
REVIEW = "review" # 審核中
APPROVED = "approved" # 已批准
ARCHIVED = "archived" # 已封存
# 2026-04-04 Claude Code: Phase 25 P1 — ANTI_PATTERN 直接發布,無需審核
PUBLISHED = "published" # 已發布ANTI_PATTERN 用,無需人工審核)
# =============================================================================
# Pydantic Models
# =============================================================================
class KnowledgeEntryCreate(BaseModel):
"""建立知識條目 Request"""
title: str = Field(..., min_length=1, max_length=255)
content: str = Field(..., min_length=1)
entry_type: EntryType
category: str = Field(..., min_length=1, max_length=100)
tags: list[str] = Field(default_factory=list)
source: EntrySource = EntrySource.HUMAN
status: EntryStatus = EntryStatus.DRAFT
related_incident_id: str | None = None
related_playbook_id: str | None = None
# P1-1 2026-04-28 ogt + Claude Sonnet 4.6: M4 補反查鏈 — approval → KM 關聯
# phase26_incident_km_integration.sql 已建立 related_approval_id 欄位與 partial index
related_approval_id: str | None = None
# P1-1 M3 2026-04-28 ogt + Claude Sonnet 4.6: 冪等 key與 related_incident_id 組合)
# migration: p1_1_km_idempotent_path_type.sql
path_type: str | None = None
# 2026-04-04 ogt: Phase 25 P1 — Anti-Pattern 閉環用症狀 hash
symptoms_hash: str | None = None
created_by: str | None = None
class KnowledgeEntryUpdate(BaseModel):
"""更新知識條目 Request"""
title: str | None = None
content: str | None = None
entry_type: EntryType | None = None
category: str | None = None
tags: list[str] | None = None
status: EntryStatus | None = None
class KnowledgeEntry(BaseModel):
"""知識條目完整模型"""
id: str
title: str
content: str
entry_type: EntryType
category: str
tags: list[str] = Field(default_factory=list)
source: EntrySource
status: EntryStatus = EntryStatus.DRAFT
related_incident_id: str | None = None
related_playbook_id: str | None = None
# P1-1 2026-04-28 ogt + Claude Sonnet 4.6: M4 補反查鏈
related_approval_id: str | None = None
# P1-1 M3 2026-04-28 ogt + Claude Sonnet 4.6: 冪等 key
path_type: str | None = None
# 2026-04-04 ogt: Phase 25 P1 — Anti-Pattern 閉環攔截用的症狀 hashSymptomPattern.compute_hash()
symptoms_hash: str | None = None
view_count: int = 0
created_by: str | None = None
created_at: datetime = Field(default_factory=now_taipei)
updated_at: datetime = Field(default_factory=now_taipei)
model_config = {"from_attributes": True}
class CategoryCount(BaseModel):
"""分類統計"""
category: str
count: int
class KnowledgeListResponse(BaseModel):
"""列表回應"""
items: list[KnowledgeEntry]
total: int
categories: list[CategoryCount] = Field(default_factory=list)