-
Notifications
You must be signed in to change notification settings - Fork 30
feat(memory): Add SOS Memory Service integration #50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
servathadi
wants to merge
1
commit into
google:main
Choose a base branch
from
servathadi:feat/sos-memory-service
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| # SOS Memory Agent Sample | ||
|
|
||
| This sample demonstrates using **SOS (Sovereign Operating System) Mirror** as a memory backend for ADK agents. | ||
|
|
||
| ## What is SOS Mirror? | ||
|
|
||
| SOS Mirror is a semantic memory system with unique features: | ||
|
|
||
| - **FRC Physics**: Memories are ranked by Frequency (access count), Recency (time decay), and Context (semantic relevance) | ||
| - **Lineage Tracking**: Every memory has a cryptographic hash chain for provenance | ||
| - **Multi-Agent Isolation**: Each agent has its own memory namespace | ||
| - **Semantic Search**: Vector embeddings for similarity-based retrieval | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| 1. **SOS Mirror API** running locally or remotely | ||
| - See: https://github.com/servathadi/sos | ||
|
|
||
| 2. **Environment variables**: | ||
| ```bash | ||
| export SOS_MIRROR_URL="http://localhost:8844" # or your deployment URL | ||
| export SOS_API_KEY="your-api-key" | ||
| export GOOGLE_API_KEY="your-gemini-key" | ||
| ``` | ||
|
|
||
| ## Quick Start | ||
|
|
||
| ```bash | ||
| # Install dependencies | ||
| pip install google-adk google-adk-community | ||
|
|
||
| # Run the agent | ||
| cd contributing/samples/sos_memory | ||
| python main.py | ||
| ``` | ||
|
|
||
| ## Using with ADK CLI | ||
|
|
||
| ```bash | ||
| # Start web interface | ||
| adk web sos_memory_agent | ||
|
|
||
| # Or run in terminal | ||
| adk run sos_memory_agent | ||
| ``` | ||
|
|
||
| ## Configuration | ||
|
|
||
| The `SOSMemoryServiceConfig` allows customization: | ||
|
|
||
| ```python | ||
| from google.adk_community.memory import SOSMemoryService, SOSMemoryServiceConfig | ||
|
|
||
| config = SOSMemoryServiceConfig( | ||
| search_top_k=10, # Max memories per search | ||
| timeout=30.0, # Request timeout | ||
| user_content_salience=0.8, # Weight for user messages | ||
| model_content_salience=0.7,# Weight for model responses | ||
| enable_lineage_tracking=True, | ||
| ) | ||
|
|
||
| memory_service = SOSMemoryService( | ||
| base_url="https://mirror.example.com", | ||
| api_key="your-key", | ||
| agent_id="my-agent", | ||
| config=config, | ||
| ) | ||
| ``` | ||
|
|
||
| ## How FRC Physics Works | ||
|
|
||
| When searching memory, SOS ranks results using: | ||
|
|
||
| ``` | ||
| score = α·frequency + β·recency + γ·context_similarity | ||
| ``` | ||
|
|
||
| Where: | ||
| - **Frequency**: How often a memory has been accessed (builds importance over time) | ||
| - **Recency**: Time decay function (recent memories score higher) | ||
| - **Context**: Cosine similarity between query and memory embeddings | ||
|
|
||
| This means frequently-accessed, recent, and semantically-relevant memories surface first. | ||
|
|
||
| ## Lineage Tracking | ||
|
|
||
| Every memory gets a lineage hash: | ||
|
|
||
| ```python | ||
| hash = SHA256(previous_hash + agent_id + content + context)[:16] | ||
| ``` | ||
|
|
||
| This creates an immutable chain of memory provenance, useful for: | ||
| - Auditing agent decisions | ||
| - Debugging conversation flows | ||
| - Ensuring memory integrity | ||
|
|
||
| ## Learn More | ||
|
|
||
| - [SOS GitHub](https://github.com/servathadi/sos) | ||
| - [ADK Documentation](https://google.github.io/adk-docs/) | ||
| - [ADK Community](https://github.com/google/adk-python-community) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| # Copyright 2025 Google LLC | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| """Main entry point for SOS Memory Agent sample. | ||
|
|
||
| This sample demonstrates how to use SOS Mirror as a memory backend | ||
| for ADK agents. SOS provides semantic memory with FRC physics and | ||
| lineage tracking for memory provenance. | ||
|
|
||
| Prerequisites: | ||
| 1. Set up SOS Mirror API (https://github.com/servathadi/sos) | ||
| 2. Set environment variables: | ||
| - SOS_MIRROR_URL: URL of SOS Mirror API (default: http://localhost:8844) | ||
| - SOS_API_KEY: API key for authentication | ||
| - GOOGLE_API_KEY: Gemini API key | ||
|
|
||
| Usage: | ||
| # Start the agent server | ||
| python main.py | ||
|
|
||
| # Or use ADK CLI | ||
| adk web sos_memory_agent | ||
| """ | ||
|
|
||
| import os | ||
| from google.adk.runners import Runner | ||
| from google.adk.sessions import InMemorySessionService | ||
| from google.adk_community.memory import SOSMemoryService, SOSMemoryServiceConfig | ||
|
|
||
| from sos_memory_agent import root_agent | ||
|
|
||
|
|
||
| def create_memory_service() -> SOSMemoryService: | ||
| """Create and configure SOS Memory service.""" | ||
| base_url = os.environ.get("SOS_MIRROR_URL", "http://localhost:8844") | ||
| api_key = os.environ.get("SOS_API_KEY", "") | ||
|
|
||
| if not api_key: | ||
| raise ValueError( | ||
| "SOS_API_KEY environment variable is required. " | ||
| "Get your API key from your SOS Mirror deployment." | ||
| ) | ||
|
|
||
| config = SOSMemoryServiceConfig( | ||
| search_top_k=10, | ||
| timeout=30.0, | ||
| user_content_salience=0.8, | ||
| model_content_salience=0.7, | ||
| enable_lineage_tracking=True, | ||
| ) | ||
|
|
||
| return SOSMemoryService( | ||
| base_url=base_url, | ||
| api_key=api_key, | ||
| agent_id="sos_memory_agent", | ||
| config=config, | ||
| ) | ||
|
|
||
|
|
||
| def main(): | ||
| """Run the SOS Memory Agent.""" | ||
| memory_service = create_memory_service() | ||
| session_service = InMemorySessionService() | ||
|
|
||
| runner = Runner( | ||
| agent=root_agent, | ||
| app_name="sos_memory_sample", | ||
| session_service=session_service, | ||
| memory_service=memory_service, | ||
| ) | ||
|
|
||
| # Start the web interface | ||
| runner.run() | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| main() |
19 changes: 19 additions & 0 deletions
19
contributing/samples/sos_memory/sos_memory_agent/__init__.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| # Copyright 2025 Google LLC | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| """SOS Memory Agent sample package.""" | ||
|
|
||
| from .agent import root_agent | ||
|
|
||
| __all__ = ["root_agent"] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| # Copyright 2025 Google LLC | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| """SOS Memory Agent - Agent with semantic memory via SOS Mirror API. | ||
|
|
||
| This sample demonstrates using SOS (Sovereign Operating System) Mirror | ||
| for agent memory. SOS provides: | ||
|
|
||
| - FRC Physics: Memories ranked by Frequency, Recency, and Context relevance | ||
| - Lineage Tracking: Cryptographic provenance for every memory | ||
| - Multi-Agent Isolation: Each agent has its own memory namespace | ||
| - Semantic Search: Vector-based similarity matching | ||
| """ | ||
|
|
||
| from datetime import datetime | ||
| from google.adk import Agent | ||
| from google.adk.agents.callback_context import CallbackContext | ||
| from google.adk.tools import load_memory, preload_memory | ||
|
|
||
|
|
||
| def update_current_time(callback_context: CallbackContext): | ||
| """Update the current time in agent state for temporal awareness.""" | ||
| callback_context.state['_time'] = datetime.now().isoformat() | ||
|
|
||
|
|
||
| root_agent = Agent( | ||
| model='gemini-2.0-flash', | ||
| name='sos_memory_agent', | ||
| description=( | ||
| 'Agent with semantic memory powered by SOS Mirror. ' | ||
| 'Uses FRC physics for intelligent memory retrieval and ' | ||
| 'lineage tracking for memory provenance.' | ||
| ), | ||
| before_agent_callback=update_current_time, | ||
| instruction=( | ||
| 'You are a helpful assistant with access to persistent semantic memory.\n\n' | ||
| 'Your memory is powered by SOS Mirror, which uses FRC physics to retrieve ' | ||
| 'the most relevant memories based on:\n' | ||
| '- Frequency: How often a memory has been accessed\n' | ||
| '- Recency: How recent the memory is\n' | ||
| '- Context: Semantic relevance to the current query\n\n' | ||
| 'When the user asks a question:\n' | ||
| '1. First, use load_memory to search for relevant past conversations\n' | ||
| '2. If the first search yields no results, try different keywords\n' | ||
| '3. Use remembered context to provide personalized responses\n' | ||
| '4. Reference past interactions when relevant ("As we discussed before...")\n\n' | ||
| 'Current time: {_time}' | ||
| ), | ||
| tools=[preload_memory, load_memory], | ||
| ) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The formula for the lineage hash in the README is slightly different from the actual implementation. The implementation uses colons to separate the components of the string being hashed. To avoid confusion, it would be best to update the example to reflect this.