genome-memory 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- genome/__init__.py +75 -0
- genome/adapters/__init__.py +10 -0
- genome/adapters/langchain.py +188 -0
- genome/adapters/llamaindex.py +133 -0
- genome/agent/__init__.py +41 -0
- genome/agent/memory.py +281 -0
- genome/agent/tools.py +173 -0
- genome/benchmark.py +235 -0
- genome/cli.py +59 -0
- genome/corpus.py +136 -0
- genome/dataset.py +35 -0
- genome/embeddings.py +152 -0
- genome/errors.py +84 -0
- genome/evals/__init__.py +30 -0
- genome/evals/baselines.py +409 -0
- genome/evals/llm_judge.py +346 -0
- genome/evals/locomo.py +1538 -0
- genome/evals/tempbelief.py +355 -0
- genome/evaluate.py +90 -0
- genome/mcp/__init__.py +4 -0
- genome/mcp/server.py +125 -0
- genome/memory/__init__.py +45 -0
- genome/memory/async_facade.py +348 -0
- genome/memory/belief.py +372 -0
- genome/memory/cache.py +157 -0
- genome/memory/conflict.py +179 -0
- genome/memory/consolidation.py +162 -0
- genome/memory/entities.py +337 -0
- genome/memory/extraction.py +197 -0
- genome/memory/facade.py +1388 -0
- genome/memory/graph.py +84 -0
- genome/memory/hybrid.py +89 -0
- genome/memory/postgres_store.py +537 -0
- genome/memory/raptor.py +261 -0
- genome/memory/rerank.py +68 -0
- genome/memory/schema.py +149 -0
- genome/memory/sqlite_store.py +402 -0
- genome/memory/store.py +117 -0
- genome/memory/temporal.py +351 -0
- genome/memory_benchmark.py +478 -0
- genome/metrics.py +114 -0
- genome/observability.py +411 -0
- genome/operators.py +188 -0
- genome/server/__init__.py +13 -0
- genome/server/__main__.py +25 -0
- genome/server/app.py +517 -0
- genome/server/models.py +176 -0
- genome/synthesis.py +183 -0
- genome/viz.py +67 -0
- genome_memory-1.0.0.dist-info/METADATA +307 -0
- genome_memory-1.0.0.dist-info/RECORD +56 -0
- genome_memory-1.0.0.dist-info/WHEEL +5 -0
- genome_memory-1.0.0.dist-info/entry_points.txt +3 -0
- genome_memory-1.0.0.dist-info/licenses/LICENSE +201 -0
- genome_memory-1.0.0.dist-info/licenses/NOTICE +7 -0
- genome_memory-1.0.0.dist-info/top_level.txt +1 -0
genome/__init__.py
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"""GENOME: DNA-inspired memory primitives for AI."""
|
|
2
|
+
|
|
3
|
+
# Copyright 2026 Northtek (FrostByte Digital LLC)
|
|
4
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
|
|
6
|
+
__version__ = "1.0.0"
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
_RELATION_CONSTANTS = {"SUPERSEDES", "CONTRADICTS", "DERIVED_FROM", "RELATES_TO", "CAUSES"}
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
_OBSERVABILITY_EXPORTS = {
|
|
13
|
+
"ErrorCapture", "CapturedError", "get_error_capture",
|
|
14
|
+
"MetricsRegistry", "get_metrics", "configure_logging", "get_logger",
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
_CONFLICT_EXPORTS = {"ConflictResolver", "ConflictDecision"}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def __getattr__(name: str):
|
|
21
|
+
# Lazy imports to avoid loading heavy deps (torch, sentence-transformers) on
|
|
22
|
+
# every `import genome`. The user pays for what they use.
|
|
23
|
+
if name == "Memory":
|
|
24
|
+
from genome.memory import Memory
|
|
25
|
+
return Memory
|
|
26
|
+
if name == "AsyncMemory":
|
|
27
|
+
from genome.memory import AsyncMemory
|
|
28
|
+
return AsyncMemory
|
|
29
|
+
if name == "MemoryRecord":
|
|
30
|
+
from genome.memory import MemoryRecord
|
|
31
|
+
return MemoryRecord
|
|
32
|
+
if name == "SearchResult":
|
|
33
|
+
from genome.memory import SearchResult
|
|
34
|
+
return SearchResult
|
|
35
|
+
if name == "MemoryEdge":
|
|
36
|
+
from genome.memory import MemoryEdge
|
|
37
|
+
return MemoryEdge
|
|
38
|
+
if name == "EmbeddingProvider":
|
|
39
|
+
from genome.embeddings import EmbeddingProvider
|
|
40
|
+
return EmbeddingProvider
|
|
41
|
+
if name in _RELATION_CONSTANTS:
|
|
42
|
+
from genome.memory import graph as _graph
|
|
43
|
+
return getattr(_graph, name)
|
|
44
|
+
if name in _OBSERVABILITY_EXPORTS:
|
|
45
|
+
from genome import observability as _obs
|
|
46
|
+
return getattr(_obs, name)
|
|
47
|
+
if name in _CONFLICT_EXPORTS:
|
|
48
|
+
from genome.memory import conflict as _conflict
|
|
49
|
+
return getattr(_conflict, name)
|
|
50
|
+
raise AttributeError(f"module 'genome' has no attribute {name!r}")
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
__all__ = [
|
|
54
|
+
"Memory",
|
|
55
|
+
"AsyncMemory",
|
|
56
|
+
"MemoryRecord",
|
|
57
|
+
"SearchResult",
|
|
58
|
+
"MemoryEdge",
|
|
59
|
+
"EmbeddingProvider",
|
|
60
|
+
"SUPERSEDES",
|
|
61
|
+
"CONTRADICTS",
|
|
62
|
+
"DERIVED_FROM",
|
|
63
|
+
"RELATES_TO",
|
|
64
|
+
"CAUSES",
|
|
65
|
+
"ErrorCapture",
|
|
66
|
+
"CapturedError",
|
|
67
|
+
"get_error_capture",
|
|
68
|
+
"MetricsRegistry",
|
|
69
|
+
"get_metrics",
|
|
70
|
+
"configure_logging",
|
|
71
|
+
"get_logger",
|
|
72
|
+
"ConflictResolver",
|
|
73
|
+
"ConflictDecision",
|
|
74
|
+
"__version__",
|
|
75
|
+
]
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"""Framework adapters for genome.
|
|
2
|
+
|
|
3
|
+
Each adapter is soft-optional: importing `genome.adapters.langchain` only fails
|
|
4
|
+
if the user tries to use it without langchain installed. Core genome has zero
|
|
5
|
+
framework dependencies.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
# Copyright 2026 Northtek (FrostByte Digital LLC)
|
|
9
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
10
|
+
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
"""LangChain adapter.
|
|
2
|
+
|
|
3
|
+
Two classes exposed:
|
|
4
|
+
|
|
5
|
+
1. `GenomeChatMessageHistory` -- implements `BaseChatMessageHistory`. Persists
|
|
6
|
+
conversation turns as memories in a genome store, scoped by `session_id`.
|
|
7
|
+
Drop-in replacement for `ChatMessageHistory` / `FileChatMessageHistory`.
|
|
8
|
+
|
|
9
|
+
2. `GenomeRetrieverMemory` -- implements `BaseMemory` for retrieval-augmented
|
|
10
|
+
chat. Calls `Memory.search` to surface relevant historical memories for the
|
|
11
|
+
current prompt. Use this in LangChain chains that want semantic recall.
|
|
12
|
+
|
|
13
|
+
Install: `pip install langchain-core` (genome does not depend on it).
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
# Copyright 2026 Northtek (FrostByte Digital LLC)
|
|
17
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
from typing import TYPE_CHECKING, Any
|
|
22
|
+
|
|
23
|
+
from genome.memory.facade import Memory
|
|
24
|
+
|
|
25
|
+
if TYPE_CHECKING:
|
|
26
|
+
# Only imported for type checking; runtime import happens lazily below.
|
|
27
|
+
from langchain_core.messages import BaseMessage
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _require_langchain():
|
|
31
|
+
try:
|
|
32
|
+
from langchain_core.messages import AIMessage, BaseMessage, HumanMessage
|
|
33
|
+
except ImportError as e:
|
|
34
|
+
raise ImportError(
|
|
35
|
+
"langchain adapter requires langchain-core. "
|
|
36
|
+
"Install with: pip install langchain-core"
|
|
37
|
+
) from e
|
|
38
|
+
return AIMessage, HumanMessage, BaseMessage
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class GenomeChatMessageHistory:
|
|
42
|
+
"""A BaseChatMessageHistory backed by a genome Memory store.
|
|
43
|
+
|
|
44
|
+
Each message (human or AI) becomes a memory. The session_id scopes them via
|
|
45
|
+
user_id, so multiple concurrent conversations stay isolated.
|
|
46
|
+
|
|
47
|
+
Usage::
|
|
48
|
+
|
|
49
|
+
from genome import Memory
|
|
50
|
+
from genome.adapters.langchain import GenomeChatMessageHistory
|
|
51
|
+
|
|
52
|
+
mem = Memory(storage="chat.db")
|
|
53
|
+
history = GenomeChatMessageHistory(memory=mem, session_id="session_123")
|
|
54
|
+
# Use as a normal LangChain BaseChatMessageHistory
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
def __init__(self, memory: Memory, session_id: str) -> None:
|
|
58
|
+
_require_langchain() # will raise if not installed
|
|
59
|
+
self.memory = memory
|
|
60
|
+
self.session_id = session_id
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def messages(self) -> list[BaseMessage]:
|
|
64
|
+
from langchain_core.messages import AIMessage, HumanMessage
|
|
65
|
+
records = self.memory.list_all(user_id=self.session_id)
|
|
66
|
+
records.sort(key=lambda r: r.created_at)
|
|
67
|
+
out: list[BaseMessage] = []
|
|
68
|
+
for r in records:
|
|
69
|
+
role = r.metadata.get("role", "human")
|
|
70
|
+
if role == "ai":
|
|
71
|
+
out.append(AIMessage(content=r.content))
|
|
72
|
+
else:
|
|
73
|
+
out.append(HumanMessage(content=r.content))
|
|
74
|
+
return out
|
|
75
|
+
|
|
76
|
+
def add_message(self, message: BaseMessage) -> None:
|
|
77
|
+
role = "ai" if message.__class__.__name__ == "AIMessage" else "human"
|
|
78
|
+
self.memory.add(
|
|
79
|
+
str(message.content),
|
|
80
|
+
user_id=self.session_id,
|
|
81
|
+
metadata={"role": role, "source": "chat"},
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
def add_messages(self, messages) -> None:
|
|
85
|
+
"""Bulk add. Part of the current BaseChatMessageHistory contract --
|
|
86
|
+
RunnableWithMessageHistory calls this rather than add_message."""
|
|
87
|
+
for m in messages:
|
|
88
|
+
self.add_message(m)
|
|
89
|
+
|
|
90
|
+
def add_user_message(self, message: str) -> None:
|
|
91
|
+
self.memory.add(
|
|
92
|
+
message,
|
|
93
|
+
user_id=self.session_id,
|
|
94
|
+
metadata={"role": "human", "source": "chat"},
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
def add_ai_message(self, message: str) -> None:
|
|
98
|
+
self.memory.add(
|
|
99
|
+
message,
|
|
100
|
+
user_id=self.session_id,
|
|
101
|
+
metadata={"role": "ai", "source": "chat"},
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
def clear(self) -> None:
|
|
105
|
+
self.memory.reset(user_id=self.session_id)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class GenomeRetrieverMemory:
|
|
109
|
+
"""A BaseMemory-compatible class that injects relevant historical memories
|
|
110
|
+
into the chain's variables on each call.
|
|
111
|
+
|
|
112
|
+
Usage::
|
|
113
|
+
|
|
114
|
+
from genome import Memory
|
|
115
|
+
from genome.adapters.langchain import GenomeRetrieverMemory
|
|
116
|
+
from langchain_core.prompts import ChatPromptTemplate
|
|
117
|
+
|
|
118
|
+
mem = Memory(storage="chat.db")
|
|
119
|
+
retriever = GenomeRetrieverMemory(
|
|
120
|
+
memory=mem, user_id="alice", memory_key="history", top_k=5,
|
|
121
|
+
)
|
|
122
|
+
prompt = ChatPromptTemplate.from_messages([
|
|
123
|
+
("system", "Relevant memories:\\n{history}"),
|
|
124
|
+
("user", "{input}"),
|
|
125
|
+
])
|
|
126
|
+
chain = prompt | llm
|
|
127
|
+
chain.invoke({"input": "what do I like?", **retriever.load_memory_variables({"input": "what do I like?"})})
|
|
128
|
+
"""
|
|
129
|
+
|
|
130
|
+
def __init__(
|
|
131
|
+
self,
|
|
132
|
+
memory: Memory,
|
|
133
|
+
*,
|
|
134
|
+
user_id: str,
|
|
135
|
+
memory_key: str = "history",
|
|
136
|
+
input_key: str = "input",
|
|
137
|
+
top_k: int = 5,
|
|
138
|
+
agent_id: str | None = None,
|
|
139
|
+
) -> None:
|
|
140
|
+
_require_langchain()
|
|
141
|
+
self.memory = memory
|
|
142
|
+
self.user_id = user_id
|
|
143
|
+
self.memory_key = memory_key
|
|
144
|
+
self.input_key = input_key
|
|
145
|
+
self.top_k = top_k
|
|
146
|
+
self.agent_id = agent_id
|
|
147
|
+
|
|
148
|
+
@property
|
|
149
|
+
def memory_variables(self) -> list[str]:
|
|
150
|
+
return [self.memory_key]
|
|
151
|
+
|
|
152
|
+
def load_memory_variables(self, inputs: dict[str, Any]) -> dict[str, str]:
|
|
153
|
+
query = inputs.get(self.input_key) or inputs.get("query") or ""
|
|
154
|
+
if not query:
|
|
155
|
+
return {self.memory_key: ""}
|
|
156
|
+
results = self.memory.search(
|
|
157
|
+
str(query),
|
|
158
|
+
user_id=self.user_id,
|
|
159
|
+
agent_id=self.agent_id,
|
|
160
|
+
limit=self.top_k,
|
|
161
|
+
)
|
|
162
|
+
lines = [f"- {r.content}" for r in results]
|
|
163
|
+
return {self.memory_key: "\n".join(lines) if lines else "(no relevant memories)"}
|
|
164
|
+
|
|
165
|
+
def save_context(self, inputs: dict[str, Any], outputs: dict[str, Any]) -> None:
|
|
166
|
+
"""Persist the turn. Both the user input and AI output become memories."""
|
|
167
|
+
user_text = str(inputs.get(self.input_key, "") or "")
|
|
168
|
+
ai_text = str(outputs.get("output", "") or outputs.get("response", "") or "")
|
|
169
|
+
if user_text:
|
|
170
|
+
self.memory.add(
|
|
171
|
+
user_text,
|
|
172
|
+
user_id=self.user_id,
|
|
173
|
+
agent_id=self.agent_id,
|
|
174
|
+
metadata={"role": "human", "source": "chat"},
|
|
175
|
+
)
|
|
176
|
+
if ai_text:
|
|
177
|
+
self.memory.add(
|
|
178
|
+
ai_text,
|
|
179
|
+
user_id=self.user_id,
|
|
180
|
+
agent_id=self.agent_id,
|
|
181
|
+
metadata={"role": "ai", "source": "chat"},
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
def clear(self) -> None:
|
|
185
|
+
self.memory.reset(user_id=self.user_id, agent_id=self.agent_id)
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
__all__ = ["GenomeChatMessageHistory", "GenomeRetrieverMemory"]
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"""LlamaIndex adapter.
|
|
2
|
+
|
|
3
|
+
Exposes `GenomeChatMemory`, a BaseMemory-compatible class for LlamaIndex
|
|
4
|
+
agents/engines that delegates storage + retrieval to genome.
|
|
5
|
+
|
|
6
|
+
Install: `pip install llama-index-core` (genome does not depend on it).
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
# Copyright 2026 Northtek (FrostByte Digital LLC)
|
|
10
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
from typing import Any
|
|
15
|
+
|
|
16
|
+
from genome.memory.facade import Memory
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _require_llamaindex():
|
|
20
|
+
try:
|
|
21
|
+
from llama_index.core.llms import ChatMessage
|
|
22
|
+
except ImportError as e:
|
|
23
|
+
raise ImportError(
|
|
24
|
+
"llamaindex adapter requires llama-index-core. "
|
|
25
|
+
"Install with: pip install llama-index-core"
|
|
26
|
+
) from e
|
|
27
|
+
return ChatMessage
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class GenomeChatMemory:
|
|
31
|
+
"""A minimal LlamaIndex-compatible ChatMemory backed by genome.
|
|
32
|
+
|
|
33
|
+
Stores each turn as a memory with role metadata. On retrieval, returns the
|
|
34
|
+
ordered sequence via `get()`, or the top-k semantically relevant via
|
|
35
|
+
`get_relevant(query)`.
|
|
36
|
+
|
|
37
|
+
Usage::
|
|
38
|
+
|
|
39
|
+
from genome import Memory
|
|
40
|
+
from genome.adapters.llamaindex import GenomeChatMemory
|
|
41
|
+
from llama_index.core.llms import ChatMessage, MessageRole
|
|
42
|
+
|
|
43
|
+
mem = Memory(storage="agent.db")
|
|
44
|
+
chat_memory = GenomeChatMemory(memory=mem, session_id="session_1")
|
|
45
|
+
chat_memory.put(ChatMessage(role=MessageRole.USER, content="hello"))
|
|
46
|
+
messages = chat_memory.get() # ordered history
|
|
47
|
+
relevant = chat_memory.get_relevant("what did I say about coffee?", top_k=3)
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
def __init__(
|
|
51
|
+
self,
|
|
52
|
+
memory: Memory,
|
|
53
|
+
*,
|
|
54
|
+
session_id: str,
|
|
55
|
+
token_limit: int | None = None,
|
|
56
|
+
) -> None:
|
|
57
|
+
_require_llamaindex()
|
|
58
|
+
self.memory = memory
|
|
59
|
+
self.session_id = session_id
|
|
60
|
+
self.token_limit = token_limit
|
|
61
|
+
|
|
62
|
+
def put(self, message: Any) -> None:
|
|
63
|
+
"""Add a ChatMessage to memory."""
|
|
64
|
+
role = str(getattr(getattr(message, "role", None), "value", message.role)).lower()
|
|
65
|
+
content = str(message.content)
|
|
66
|
+
self.memory.add(
|
|
67
|
+
content,
|
|
68
|
+
user_id=self.session_id,
|
|
69
|
+
metadata={"role": role, "source": "chat"},
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
def set(self, messages: list[Any]) -> None:
|
|
73
|
+
"""Replace all messages in this session."""
|
|
74
|
+
self.memory.reset(user_id=self.session_id)
|
|
75
|
+
for m in messages:
|
|
76
|
+
self.put(m)
|
|
77
|
+
|
|
78
|
+
def get(self, input: str | None = None, **kwargs: Any) -> list[Any]:
|
|
79
|
+
"""Return the full chronological message history for this session.
|
|
80
|
+
|
|
81
|
+
Accepts LlamaIndex's `get(input=..., **kwargs)` call signature (the
|
|
82
|
+
agent runtime passes the current user message as `input`) so this
|
|
83
|
+
object is drop-in usable there. `input` is accepted for compatibility;
|
|
84
|
+
chronological history is returned regardless -- use `get_relevant()`
|
|
85
|
+
for retrieval-aware recall.
|
|
86
|
+
"""
|
|
87
|
+
from llama_index.core.llms import ChatMessage, MessageRole
|
|
88
|
+
records = self.memory.list_all(user_id=self.session_id)
|
|
89
|
+
records.sort(key=lambda r: r.created_at)
|
|
90
|
+
out: list[ChatMessage] = []
|
|
91
|
+
for r in records:
|
|
92
|
+
role_str = r.metadata.get("role", "user").lower()
|
|
93
|
+
role = {
|
|
94
|
+
"user": MessageRole.USER,
|
|
95
|
+
"human": MessageRole.USER,
|
|
96
|
+
"ai": MessageRole.ASSISTANT,
|
|
97
|
+
"assistant": MessageRole.ASSISTANT,
|
|
98
|
+
"system": MessageRole.SYSTEM,
|
|
99
|
+
}.get(role_str, MessageRole.USER)
|
|
100
|
+
out.append(ChatMessage(role=role, content=r.content))
|
|
101
|
+
return out
|
|
102
|
+
|
|
103
|
+
def get_all(self, **kwargs: Any) -> list[Any]:
|
|
104
|
+
"""Alias for get() -- matches LlamaIndex BaseMemory naming."""
|
|
105
|
+
return self.get()
|
|
106
|
+
|
|
107
|
+
def get_relevant(self, query: str, top_k: int = 5) -> list[Any]:
|
|
108
|
+
"""Return the top-k semantically relevant historical messages for the query.
|
|
109
|
+
|
|
110
|
+
genome-specific: this is the recall-style retrieval that matters for
|
|
111
|
+
long-running agents whose full history exceeds the context window.
|
|
112
|
+
"""
|
|
113
|
+
from llama_index.core.llms import ChatMessage, MessageRole
|
|
114
|
+
results = self.memory.search(query, user_id=self.session_id, limit=top_k)
|
|
115
|
+
out: list[ChatMessage] = []
|
|
116
|
+
for r in results:
|
|
117
|
+
role_str = r.record.metadata.get("role", "user").lower()
|
|
118
|
+
role = {
|
|
119
|
+
"user": MessageRole.USER,
|
|
120
|
+
"human": MessageRole.USER,
|
|
121
|
+
"ai": MessageRole.ASSISTANT,
|
|
122
|
+
"assistant": MessageRole.ASSISTANT,
|
|
123
|
+
"system": MessageRole.SYSTEM,
|
|
124
|
+
}.get(role_str, MessageRole.USER)
|
|
125
|
+
out.append(ChatMessage(role=role, content=r.content))
|
|
126
|
+
return out
|
|
127
|
+
|
|
128
|
+
def reset(self) -> None:
|
|
129
|
+
"""Clear this session's history."""
|
|
130
|
+
self.memory.reset(user_id=self.session_id)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
__all__ = ["GenomeChatMemory"]
|
genome/agent/__init__.py
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""Agent runtime for genome.
|
|
2
|
+
|
|
3
|
+
Letta-style hierarchical memory (core + archival) with tool-callable
|
|
4
|
+
interfaces. Works with any LLM SDK (Anthropic, OpenAI, any tool-calling
|
|
5
|
+
model) by exposing tool schemas the agent can invoke.
|
|
6
|
+
|
|
7
|
+
Usage::
|
|
8
|
+
|
|
9
|
+
from genome import Memory
|
|
10
|
+
from genome.agent import AgentMemory, tool_schemas
|
|
11
|
+
|
|
12
|
+
mem = Memory(storage="agent.db")
|
|
13
|
+
agent_mem = AgentMemory(memory=mem, user_id="alice", session_id="s1")
|
|
14
|
+
|
|
15
|
+
# Render the core memory block into your system prompt
|
|
16
|
+
system_prompt = f"You are a helpful assistant.\\n\\n{agent_mem.render_core()}"
|
|
17
|
+
|
|
18
|
+
# Advertise the memory tools to your LLM
|
|
19
|
+
tools = tool_schemas() # Anthropic format
|
|
20
|
+
|
|
21
|
+
# When the LLM calls a tool:
|
|
22
|
+
result = agent_mem.handle_tool_call(tool_name, tool_args)
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
# Copyright 2026 Northtek (FrostByte Digital LLC)
|
|
26
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
27
|
+
|
|
28
|
+
from genome.agent.memory import AgentMemory, CoreBlock
|
|
29
|
+
from genome.agent.tools import (
|
|
30
|
+
ANTHROPIC_TOOL_SCHEMAS,
|
|
31
|
+
OPENAI_TOOL_SCHEMAS,
|
|
32
|
+
tool_schemas,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
__all__ = [
|
|
36
|
+
"AgentMemory",
|
|
37
|
+
"CoreBlock",
|
|
38
|
+
"tool_schemas",
|
|
39
|
+
"ANTHROPIC_TOOL_SCHEMAS",
|
|
40
|
+
"OPENAI_TOOL_SCHEMAS",
|
|
41
|
+
]
|