feat(api): Knowledge Base Phase 1 後端四層架構
- models/knowledge.py: Pydantic Schema (EntryType/Source/Status/CRUD)
- db/models.py: KnowledgeEntryRecord ORM (PostgreSQL)
- repositories/interfaces.py: IKnowledgeRepository Protocol
- repositories/knowledge_repository.py: PostgreSQL CRUD 實作
- services/knowledge_service.py: 業務邏輯 (get_db_context 內部管理 session)
- api/v1/knowledge.py: REST Router (get_knowledge_service,無直接 DB 存取)
- main.py: 掛載 Knowledge Base Router
- k8s/jobs/migrate-knowledge-entries.yaml: DB Migration Job
API 端點: GET/POST / | GET/PATCH/DELETE /{id} | POST /{id}/approve
GET /search | GET /categories
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
109
apps/api/src/models/knowledge.py
Normal file
109
apps/api/src/models/knowledge.py
Normal file
@@ -0,0 +1,109 @@
|
||||
"""
|
||||
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" # 事後分析報告
|
||||
|
||||
|
||||
class EntrySource(str, Enum):
|
||||
"""知識來源"""
|
||||
AI_EXTRACTED = "ai_extracted" # AI 自動萃取
|
||||
HUMAN = "human" # 人工建立
|
||||
|
||||
|
||||
class EntryStatus(str, Enum):
|
||||
"""知識條目狀態"""
|
||||
DRAFT = "draft" # 草稿
|
||||
REVIEW = "review" # 審核中
|
||||
APPROVED = "approved" # 已批准
|
||||
ARCHIVED = "archived" # 已封存
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# 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
|
||||
related_incident_id: str | None = None
|
||||
related_playbook_id: 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
|
||||
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)
|
||||
Reference in New Issue
Block a user