New packages: - packages/lewooogo-brain: AI reasoning & decision engine - IProposalEngine interface (ABC) - IIncidentProcessor interface (ABC) - Pydantic models: Proposal, Guardrails, Incident, Signal - packages/lewooogo-data: Memory provider abstraction - IMemoryProvider interface (ABC) - IDualMemoryProvider for Working + Episodic memory - Generic type support for flexible data models Documentation: - ADR-008: Python modular packages architecture decision - ARCHITECTURE_MEMORY.md: Module map index for AI developers - LOGBOOK.md: Updated milestones and Phase 6.4 status Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
170 lines
3.7 KiB
Python
170 lines
3.7 KiB
Python
"""
|
||
IMemoryProvider - 記憶體提供者介面
|
||
===================================
|
||
|
||
定義資料存取的標準介面
|
||
|
||
記憶層級:
|
||
- Working Memory (Redis): 7 天 TTL,快速存取
|
||
- Episodic Memory (PG/SQLite): 永久保存,可查詢
|
||
|
||
統帥鐵律:
|
||
- 禁止直接存取底層資料庫
|
||
- 所有存取必須透過 Provider 抽象
|
||
- 雙層寫入:Working + Episodic 同步
|
||
"""
|
||
|
||
from abc import ABC, abstractmethod
|
||
from typing import Any, TypeVar, Generic
|
||
from pydantic import BaseModel
|
||
|
||
|
||
T = TypeVar("T", bound=BaseModel)
|
||
|
||
|
||
class IMemoryProvider(ABC, Generic[T]):
|
||
"""
|
||
記憶體提供者介面
|
||
|
||
職責:
|
||
1. 提供統一的資料存取抽象
|
||
2. 隱藏底層實作細節 (Redis/PG/SQLite)
|
||
3. 支援 TTL 與永久保存
|
||
|
||
使用方式:
|
||
class RedisMemory(IMemoryProvider[Incident]):
|
||
async def load(self, key: str) -> Incident | None:
|
||
# 實作 Redis 存取
|
||
pass
|
||
|
||
class PgMemory(IMemoryProvider[Incident]):
|
||
async def load(self, key: str) -> Incident | None:
|
||
# 實作 PostgreSQL 存取
|
||
pass
|
||
"""
|
||
|
||
@abstractmethod
|
||
async def load(self, key: str) -> T | None:
|
||
"""
|
||
載入資料
|
||
|
||
Args:
|
||
key: 資料鍵值
|
||
|
||
Returns:
|
||
T | None: 資料物件或 None
|
||
"""
|
||
...
|
||
|
||
@abstractmethod
|
||
async def save(self, key: str, data: T, ttl_seconds: int | None = None) -> bool:
|
||
"""
|
||
儲存資料
|
||
|
||
Args:
|
||
key: 資料鍵值
|
||
data: 資料物件
|
||
ttl_seconds: 過期時間 (秒),None 表示永久
|
||
|
||
Returns:
|
||
bool: 是否成功
|
||
"""
|
||
...
|
||
|
||
@abstractmethod
|
||
async def delete(self, key: str) -> bool:
|
||
"""
|
||
刪除資料
|
||
|
||
Args:
|
||
key: 資料鍵值
|
||
|
||
Returns:
|
||
bool: 是否成功
|
||
"""
|
||
...
|
||
|
||
@abstractmethod
|
||
async def exists(self, key: str) -> bool:
|
||
"""
|
||
檢查資料是否存在
|
||
|
||
Args:
|
||
key: 資料鍵值
|
||
|
||
Returns:
|
||
bool: 是否存在
|
||
"""
|
||
...
|
||
|
||
@abstractmethod
|
||
async def update(self, key: str, updates: dict[str, Any]) -> bool:
|
||
"""
|
||
部分更新資料
|
||
|
||
Args:
|
||
key: 資料鍵值
|
||
updates: 要更新的欄位
|
||
|
||
Returns:
|
||
bool: 是否成功
|
||
"""
|
||
...
|
||
|
||
|
||
class IDualMemoryProvider(ABC, Generic[T]):
|
||
"""
|
||
雙層記憶體提供者介面
|
||
|
||
統帥鐵律:Working + Episodic 同步寫入
|
||
|
||
使用方式:
|
||
class DualMemory(IDualMemoryProvider[Incident]):
|
||
def __init__(self):
|
||
self.working = RedisMemory()
|
||
self.episodic = PgMemory()
|
||
|
||
async def save(self, key: str, data: Incident) -> bool:
|
||
# 同時寫入 Redis + PG
|
||
pass
|
||
"""
|
||
|
||
@property
|
||
@abstractmethod
|
||
def working(self) -> IMemoryProvider[T]:
|
||
"""Working Memory Provider (Redis)"""
|
||
...
|
||
|
||
@property
|
||
@abstractmethod
|
||
def episodic(self) -> IMemoryProvider[T]:
|
||
"""Episodic Memory Provider (PG/SQLite)"""
|
||
...
|
||
|
||
@abstractmethod
|
||
async def load(self, key: str) -> T | None:
|
||
"""
|
||
載入資料 (Working 優先,Episodic 備援)
|
||
|
||
Args:
|
||
key: 資料鍵值
|
||
|
||
Returns:
|
||
T | None: 資料物件或 None
|
||
"""
|
||
...
|
||
|
||
@abstractmethod
|
||
async def save(self, key: str, data: T) -> bool:
|
||
"""
|
||
雙層儲存 (Working + Episodic 同步)
|
||
|
||
Args:
|
||
key: 資料鍵值
|
||
data: 資料物件
|
||
|
||
Returns:
|
||
bool: 是否成功
|
||
"""
|
||
...
|