| 81 | |
| 82 | |
| 83 | class MemoryNode(BaseModel): |
| 84 | id: int | None = None |
| 85 | content: str |
| 86 | summary: str = "" |
| 87 | importance: float = 1.0 |
| 88 | access_count: int = 0 |
| 89 | timestamp: float = Field(default_factory=lambda: datetime.now(timezone.utc).timestamp()) |
| 90 | embedding: list[float] |
| 91 | |
| 92 | @classmethod |
| 93 | async def from_content(cls, content: str, deps: Deps): |
| 94 | embedding = await get_embedding(content, deps) |
| 95 | return cls(content=content, embedding=embedding) |
| 96 | |
| 97 | async def save(self, deps: Deps): |
| 98 | async with deps.pool.acquire() as conn: |
| 99 | if self.id is None: |
| 100 | result = await conn.fetchrow( |
| 101 | """ |
| 102 | INSERT INTO memories (content, summary, importance, access_count, |
| 103 | timestamp, embedding) |
| 104 | VALUES ($1, $2, $3, $4, $5, $6) |
| 105 | RETURNING id |
| 106 | """, |
| 107 | self.content, |
| 108 | self.summary, |
| 109 | self.importance, |
| 110 | self.access_count, |
| 111 | self.timestamp, |
| 112 | self.embedding, |
| 113 | ) |
| 114 | self.id = result["id"] |
| 115 | else: |
| 116 | await conn.execute( |
| 117 | """ |
| 118 | UPDATE memories |
| 119 | SET content = $1, summary = $2, importance = $3, |
| 120 | access_count = $4, timestamp = $5, embedding = $6 |
| 121 | WHERE id = $7 |
| 122 | """, |
| 123 | self.content, |
| 124 | self.summary, |
| 125 | self.importance, |
| 126 | self.access_count, |
| 127 | self.timestamp, |
| 128 | self.embedding, |
| 129 | self.id, |
| 130 | ) |
| 131 | |
| 132 | async def merge_with(self, other: Self, deps: Deps): |
| 133 | self.content = await do_ai( |
| 134 | f"{self.content}\n\n{other.content}", |
| 135 | "Combine the following two texts into a single, coherent text.", |
| 136 | str, |
| 137 | deps, |
| 138 | ) |
| 139 | self.importance += other.importance |
| 140 | self.access_count += other.access_count |
no outgoing calls
no test coverage detected