Spaces:
Sleeping
Sleeping
File size: 5,714 Bytes
a5c1fa0 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | # server/memory.py
"""
Context and memory optimization tracker.
Records what the agent has seen, how much context it consumed,
and detects wasteful patterns (re-reading, reading irrelevant content).
This answers: "How efficiently does the agent use its context window?"
"""
from typing import Dict, List, Optional
from dataclasses import dataclass, field
@dataclass
class FileReadRecord:
"""Record of a single file read."""
path: str
size_bytes: int
read_count: int
was_relevant: bool
first_read_step: int
@dataclass
class MemoryStats:
"""Comprehensive context usage statistics."""
total_bytes_read: int = 0
unique_bytes_read: int = 0
redundant_bytes_read: int = 0
total_files_read: int = 0
unique_files_read: int = 0
redundant_reads: int = 0
relevant_files_read: int = 0
irrelevant_files_read: int = 0
context_efficiency: float = 0.0 # unique_useful / total
search_queries: int = 0
total_content_written: int = 0 # bytes written by agent
def to_dict(self) -> dict:
return {
"total_bytes_read": self.total_bytes_read,
"unique_bytes_read": self.unique_bytes_read,
"redundant_bytes_read": self.redundant_bytes_read,
"total_files_read": self.total_files_read,
"unique_files_read": self.unique_files_read,
"redundant_reads": self.redundant_reads,
"relevant_files_read": self.relevant_files_read,
"irrelevant_files_read": self.irrelevant_files_read,
"context_efficiency": round(self.context_efficiency, 3),
"search_queries": self.search_queries,
"total_content_written": self.total_content_written,
}
class MemoryTracker:
"""
Tracks agent's context consumption and memory patterns.
Usage:
tracker = MemoryTracker()
tracker.start_episode(relevant_files=["src/auth.py", "tests/test_auth.py"])
tracker.record_read("src/auth.py", 500, step=1)
tracker.record_read("src/auth.py", 500, step=3) # redundant!
stats = tracker.get_stats()
"""
def __init__(self):
self._reads: Dict[str, FileReadRecord] = {}
self._relevant_files: set = set()
self._search_count: int = 0
self._bytes_written: int = 0
def start_episode(self, relevant_files: List[str] = None):
"""Reset tracker for new episode."""
self._reads.clear()
self._relevant_files = set(relevant_files or [])
self._search_count = 0
self._bytes_written = 0
def record_read(self, path: str, size_bytes: int, step: int):
"""Record a file read action."""
if path in self._reads:
self._reads[path].read_count += 1
else:
self._reads[path] = FileReadRecord(
path=path,
size_bytes=size_bytes,
read_count=1,
was_relevant=path in self._relevant_files,
first_read_step=step,
)
def record_search(self):
"""Record a search query."""
self._search_count += 1
def record_write(self, content_bytes: int):
"""Record bytes written by agent."""
self._bytes_written += content_bytes
def get_stats(self) -> MemoryStats:
"""Compute comprehensive memory statistics."""
total_bytes = 0
unique_bytes = 0
redundant_bytes = 0
redundant_reads = 0
relevant_count = 0
irrelevant_count = 0
for record in self._reads.values():
first_read_bytes = record.size_bytes
unique_bytes += first_read_bytes
total_bytes += first_read_bytes * record.read_count
if record.read_count > 1:
redundant_reads += record.read_count - 1
redundant_bytes += first_read_bytes * (record.read_count - 1)
if record.was_relevant:
relevant_count += 1
else:
irrelevant_count += 1
# Context efficiency: what fraction of bytes read was useful (relevant + unique)?
relevant_bytes = sum(
r.size_bytes for r in self._reads.values() if r.was_relevant
)
efficiency = relevant_bytes / max(1, total_bytes)
return MemoryStats(
total_bytes_read=total_bytes,
unique_bytes_read=unique_bytes,
redundant_bytes_read=redundant_bytes,
total_files_read=sum(r.read_count for r in self._reads.values()),
unique_files_read=len(self._reads),
redundant_reads=redundant_reads,
relevant_files_read=relevant_count,
irrelevant_files_read=irrelevant_count,
context_efficiency=efficiency,
search_queries=self._search_count,
total_content_written=self._bytes_written,
)
def get_wasteful_patterns(self) -> List[str]:
"""Identify specific wasteful patterns for debugging."""
patterns = []
# Files read multiple times
for record in self._reads.values():
if record.read_count > 1:
patterns.append(
f"REDUNDANT_READ: '{record.path}' read {record.read_count} times "
f"({record.size_bytes * record.read_count} bytes wasted)"
)
# Irrelevant files read
for record in self._reads.values():
if not record.was_relevant and record.read_count > 0:
patterns.append(
f"IRRELEVANT_READ: '{record.path}' not in relevant files "
f"({record.size_bytes} bytes wasted)"
)
return patterns
|