feat: add phase 2 decentralized memory python services and tests
This commit is contained in:
56
apps/coordinator-api/src/app/domain/decentralized_memory.py
Normal file
56
apps/coordinator-api/src/app/domain/decentralized_memory.py
Normal file
@@ -0,0 +1,56 @@
|
||||
"""
|
||||
Decentralized Memory Domain Models
|
||||
|
||||
Domain models for managing agent memory and knowledge graphs on IPFS/Filecoin.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
from enum import Enum
|
||||
from typing import Dict, Optional, List
|
||||
from uuid import uuid4
|
||||
|
||||
from sqlalchemy import Column, JSON
|
||||
from sqlmodel import Field, SQLModel, Relationship
|
||||
|
||||
class MemoryType(str, Enum):
|
||||
VECTOR_DB = "vector_db"
|
||||
KNOWLEDGE_GRAPH = "knowledge_graph"
|
||||
POLICY_WEIGHTS = "policy_weights"
|
||||
EPISODIC = "episodic"
|
||||
|
||||
class StorageStatus(str, Enum):
|
||||
PENDING = "pending" # Upload to IPFS pending
|
||||
UPLOADED = "uploaded" # Available on IPFS
|
||||
PINNED = "pinned" # Pinned on Filecoin/Pinata
|
||||
ANCHORED = "anchored" # CID written to blockchain
|
||||
FAILED = "failed" # Upload failed
|
||||
|
||||
class AgentMemoryNode(SQLModel, table=True):
|
||||
"""Represents a chunk of memory or knowledge stored on decentralized storage"""
|
||||
__tablename__ = "agent_memory_node"
|
||||
|
||||
id: str = Field(default_factory=lambda: uuid4().hex, primary_key=True)
|
||||
agent_id: str = Field(index=True)
|
||||
memory_type: MemoryType = Field(index=True)
|
||||
|
||||
# Decentralized Storage Identifiers
|
||||
cid: Optional[str] = Field(default=None, index=True) # IPFS Content Identifier
|
||||
size_bytes: Optional[int] = Field(default=None)
|
||||
|
||||
# Encryption and Security
|
||||
is_encrypted: bool = Field(default=True)
|
||||
encryption_key_id: Optional[str] = Field(default=None) # Reference to KMS or Lit Protocol
|
||||
zk_proof_hash: Optional[str] = Field(default=None) # Hash of the ZK proof verifying content validity
|
||||
|
||||
status: StorageStatus = Field(default=StorageStatus.PENDING, index=True)
|
||||
|
||||
metadata: Dict[str, str] = Field(default_factory=dict, sa_column=Column(JSON))
|
||||
tags: List[str] = Field(default_factory=list, sa_column=Column(JSON))
|
||||
|
||||
# Blockchain Anchoring
|
||||
anchor_tx_hash: Optional[str] = Field(default=None)
|
||||
|
||||
created_at: datetime = Field(default_factory=datetime.utcnow)
|
||||
updated_at: datetime = Field(default_factory=datetime.utcnow)
|
||||
122
apps/coordinator-api/src/app/domain/federated_learning.py
Normal file
122
apps/coordinator-api/src/app/domain/federated_learning.py
Normal file
@@ -0,0 +1,122 @@
|
||||
"""
|
||||
Federated Learning Domain Models
|
||||
|
||||
Domain models for managing cross-agent knowledge sharing and collaborative model training.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
from enum import Enum
|
||||
from typing import Dict, List, Optional
|
||||
from uuid import uuid4
|
||||
|
||||
from sqlalchemy import Column, JSON
|
||||
from sqlmodel import Field, SQLModel, Relationship
|
||||
|
||||
class TrainingStatus(str, Enum):
|
||||
INITIALIZED = "initiated"
|
||||
GATHERING_PARTICIPANTS = "gathering_participants"
|
||||
TRAINING = "training"
|
||||
AGGREGATING = "aggregating"
|
||||
COMPLETED = "completed"
|
||||
FAILED = "failed"
|
||||
|
||||
class ParticipantStatus(str, Enum):
|
||||
INVITED = "invited"
|
||||
JOINED = "joined"
|
||||
TRAINING = "training"
|
||||
SUBMITTED = "submitted"
|
||||
DROPPED = "dropped"
|
||||
|
||||
class FederatedLearningSession(SQLModel, table=True):
|
||||
"""Represents a collaborative training session across multiple agents"""
|
||||
__tablename__ = "federated_learning_session"
|
||||
|
||||
id: str = Field(default_factory=lambda: uuid4().hex, primary_key=True)
|
||||
initiator_agent_id: str = Field(index=True)
|
||||
task_description: str = Field()
|
||||
model_architecture_cid: str = Field() # IPFS CID pointing to model structure definition
|
||||
initial_weights_cid: Optional[str] = Field(default=None) # Optional starting point
|
||||
|
||||
target_participants: int = Field(default=3)
|
||||
current_round: int = Field(default=0)
|
||||
total_rounds: int = Field(default=10)
|
||||
|
||||
aggregation_strategy: str = Field(default="fedavg") # e.g. fedavg, fedprox
|
||||
min_participants_per_round: int = Field(default=2)
|
||||
|
||||
reward_pool_amount: float = Field(default=0.0) # Total AITBC allocated to reward participants
|
||||
|
||||
status: TrainingStatus = Field(default=TrainingStatus.INITIALIZED, index=True)
|
||||
|
||||
global_model_cid: Optional[str] = Field(default=None) # Final aggregated model
|
||||
|
||||
created_at: datetime = Field(default_factory=datetime.utcnow)
|
||||
updated_at: datetime = Field(default_factory=datetime.utcnow)
|
||||
|
||||
# Relationships
|
||||
participants: List["TrainingParticipant"] = Relationship(back_populates="session")
|
||||
rounds: List["TrainingRound"] = Relationship(back_populates="session")
|
||||
|
||||
class TrainingParticipant(SQLModel, table=True):
|
||||
"""An agent participating in a federated learning session"""
|
||||
__tablename__ = "training_participant"
|
||||
|
||||
id: str = Field(default_factory=lambda: uuid4().hex, primary_key=True)
|
||||
session_id: str = Field(foreign_key="federated_learning_session.id", index=True)
|
||||
agent_id: str = Field(index=True)
|
||||
|
||||
status: ParticipantStatus = Field(default=ParticipantStatus.JOINED, index=True)
|
||||
data_samples_count: int = Field(default=0) # Claimed number of local samples used
|
||||
compute_power_committed: float = Field(default=0.0) # TFLOPS
|
||||
|
||||
reputation_score_at_join: float = Field(default=0.0)
|
||||
earned_reward: float = Field(default=0.0)
|
||||
|
||||
joined_at: datetime = Field(default_factory=datetime.utcnow)
|
||||
updated_at: datetime = Field(default_factory=datetime.utcnow)
|
||||
|
||||
# Relationships
|
||||
session: FederatedLearningSession = Relationship(back_populates="participants")
|
||||
|
||||
class TrainingRound(SQLModel, table=True):
|
||||
"""A specific round of federated learning"""
|
||||
__tablename__ = "training_round"
|
||||
|
||||
id: str = Field(default_factory=lambda: uuid4().hex, primary_key=True)
|
||||
session_id: str = Field(foreign_key="federated_learning_session.id", index=True)
|
||||
round_number: int = Field()
|
||||
|
||||
status: str = Field(default="pending") # pending, active, aggregating, completed
|
||||
|
||||
starting_model_cid: str = Field() # Global model weights at start of round
|
||||
aggregated_model_cid: Optional[str] = Field(default=None) # Resulting weights after round
|
||||
|
||||
metrics: Dict[str, float] = Field(default_factory=dict, sa_column=Column(JSON)) # e.g. loss, accuracy
|
||||
|
||||
started_at: datetime = Field(default_factory=datetime.utcnow)
|
||||
completed_at: Optional[datetime] = Field(default=None)
|
||||
|
||||
# Relationships
|
||||
session: FederatedLearningSession = Relationship(back_populates="rounds")
|
||||
updates: List["LocalModelUpdate"] = Relationship(back_populates="round")
|
||||
|
||||
class LocalModelUpdate(SQLModel, table=True):
|
||||
"""A local model update submitted by a participant for a specific round"""
|
||||
__tablename__ = "local_model_update"
|
||||
|
||||
id: str = Field(default_factory=lambda: uuid4().hex, primary_key=True)
|
||||
round_id: str = Field(foreign_key="training_round.id", index=True)
|
||||
participant_agent_id: str = Field(index=True)
|
||||
|
||||
weights_cid: str = Field() # IPFS CID of the locally trained weights
|
||||
zk_proof_hash: Optional[str] = Field(default=None) # Proof that training was executed correctly
|
||||
|
||||
is_aggregated: bool = Field(default=False)
|
||||
rejected_reason: Optional[str] = Field(default=None) # e.g. "outlier", "failed zk verification"
|
||||
|
||||
submitted_at: datetime = Field(default_factory=datetime.utcnow)
|
||||
|
||||
# Relationships
|
||||
round: TrainingRound = Relationship(back_populates="updates")
|
||||
Reference in New Issue
Block a user