Python client for Satori database
Project description
📚 Satori Python SDK
A comprehensive Python client for SatoriDB - a powerful in-memory database with graph relationships, AI capabilities, and real-time features.
✨ Main Features
- Ultra-fast CRUD operations ⚡
- Advanced queries using
field_array🔍 - Real-time notifications 📢
- Graph operations - vertices, DFS, BFS, shortest path, centrality metrics 🕸️
- Data encryption and decryption 🔐
- AI-powered features - semantic search, natural language queries, mindspaces 🤖
- Mindspace operations - cognitive contexts for AI conversations 🧠
🚀 Installation
pip install satori-client
Or, if you use the repository directly:
pip install websockets uuid
🏁 Quick Start
import asyncio
from satori import Satori
async def main():
client = Satori(
username='user',
password='password',
host='ws://localhost:8000'
)
await client.connect()
# Create an object
await client.set({
'key': 'user:john',
'data': {'name': 'John Doe', 'email': 'john@example.com', 'age': 30},
'type': 'user'
})
# Get the object
user = await client.get({'key': 'user:john'})
print(user)
asyncio.run(main())
📖 API Reference
Table of Contents
- Basic Operations
- Crypto Operations
- Graph Operations
- AI Operations
- Analytics Operations
- Mindspace Operations
- Real-time Notifications
- Schema Class
- Response Format
Basic Operations
SET - Create Data
Creates a new object in the database. If no key is provided, a UUID is automatically generated.
await client.set({
'key': 'user:john', # Object key (optional, auto-generated if omitted)
'data': {'name': 'John'}, # Object data content (default: {})
'type': 'user', # Object class/type (default: "normal")
'expires': False, # Whether object expires (default: false)
'expiration_time': 1700000000 # Expiration timestamp in milliseconds
})
GET - Read Data
Retrieves one or more objects from the database. Use "*" for key to return all objects.
# Get single object
user = await client.get({'key': 'user:john'})
# Get all objects
all_objects = await client.get({'key': '*'})
# Query by field
users = await client.get({
'field_array': [
{'field': 'email', 'value': 'john@example.com'}
]
})
# Get first match only
first_user = await client.get({
'field_array': [
{'field': 'age', 'value': 30}
],
'one': True
})
# Limit results
limited = await client.get({
'field_array': [
{'field': 'type', 'value': 'user'}
],
'max': 10
})
PUT - Update Data
Updates one or more fields of an existing object.
await client.put({
'key': 'user:john',
'replace_field': 'age',
'replace_value': 31
})
# Batch update by field query
await client.put({
'field_array': [
{'field': 'type', 'value': 'user'}
],
'replace_field': 'status',
'replace_value': 'active'
})
DELETE - Delete Data
Removes one or more objects from the database.
await client.delete({'key': 'user:john'})
# Delete by field query
await client.delete({
'field_array': [
{'field': 'status', 'value': 'inactive'}
]
})
PUSH - Add to Array
Adds a value to the end of an array field.
await client.push({
'key': 'user:john',
'array': 'tags',
'value': 'premium'
})
POP - Remove Last from Array
Removes the last element from an array field.
await client.pop({
'key': 'user:john',
'array': 'notifications'
})
SPLICE - Remove First from Array
Removes the first element from an array field.
await client.splice({
'key': 'user:john',
'array': 'notifications'
})
REMOVE - Remove Specific Value
Removes a specific value from an array field.
await client.remove({
'key': 'user:john',
'array': 'tags',
'value': 'premium'
})
Crypto Operations
ENCRYPT
Encrypts an object's data using AES encryption.
await client.encrypt({
'key': 'user:john',
'encryption_key': 'secret-key-123'
})
DECRYPT
Decrypts an encrypted object.
await client.decrypt({
'key': 'user:john',
'encryption_key': 'secret-key-123'
})
Graph Operations
SET_VERTEX
Adds vertices/edges to an object for graph relationships.
# Simple vertex
await client.set_vertex({
'key': 'user:john',
'vertex': 'user:jane'
})
# Vertex with relation
await client.set_vertex({
'key': 'user:john',
'vertex': {'vertex': 'user:jane', 'relation': 'friend'}
})
# Vertex with relation and weight
await client.set_vertex({
'key': 'user:john',
'vertex': {'vertex': 'post:123', 'relation': 'author', 'weight': 1.0}
})
# Multiple vertices
await client.set_vertex({
'key': 'user:john',
'vertex': ['user:jane', 'user:alice', 'user:bob']
})
GET_VERTEX
Retrieves all vertices from an object.
vertices = await client.get_vertex({
'key': 'user:john'
})
DELETE_VERTEX
Removes a specific vertex from an object.
await client.delete_vertex({
'key': 'user:john',
'vertex': 'user:jane'
})
DFS
Performs a distributed depth-first search traversal.
# Traverse from a node
results = await client.dfs({
'node': 'user:john'
})
# Filter by relation
results = await client.dfs({
'node': 'user:john',
'relation': 'friend'
})
GRAPH_BFS
Performs breadth-first search on the graph.
# Get all reachable nodes from a starting node
results = await client.graph_bfs({
'node': 'user:john'
})
GRAPH_DFS
Performs depth-first search on the graph.
results = await client.graph_dfs({
'node': 'user:john'
})
GRAPH_SHORTEST_PATH
Finds the shortest path between two nodes using Dijkstra's algorithm.
path = await client.graph_shortest_path({
'node': 'user:john',
'target': 'post:123'
})
# Returns: ["user:john", "user:jane", "post:123"]
GRAPH_CONNECTED_COMPONENTS
Finds all connected components in the graph.
components = await client.graph_connected_components({})
# Returns: [["node1", "node2", "node3"], ["node4", "node5"], ["node6"]]
GRAPH_SCC
Finds strongly connected components using Tarjan's algorithm.
scc = await client.graph_scc({})
# Returns: [["node1", "node2", "node3"], ["node4", "node5"]]
GRAPH_DEGREE_CENTRALITY
Calculates degree centrality (number of connections) for each node.
centrality = await client.graph_degree_centrality({})
# Returns: {"node1": 5, "node2": 3, "node3": 8}
GRAPH_CLOSENESS_CENTRALITY
Calculates closeness centrality for each node.
centrality = await client.graph_closeness_centrality({})
# Returns: {"node1": 0.45, "node2": 0.32, "node3": 0.58}
GRAPH_CENTROID
Finds the centroid node (node with highest closeness centrality).
centroid = await client.graph_centroid({})
# Returns: "node-with-highest-centrality"
AI Operations
ASK
Ask questions about your data using AI-powered context gathering.
response = await client.ask({
'question': 'Which user has the most posts?',
'session': 'global', # Mindspace session (default: "global")
'backend': 'openai' # LLM backend: "ollama" or "openai"
})
# Returns: {"response": "AI-generated answer...", "context": [...], "session": "..."}
ANN / GET_SIMILAR
Performs approximate nearest neighbor search using vector embeddings.
# Using existing object's embedding
results = await client.ann({
'key': 'user:john',
'k': 10, # Number of neighbors (default: 5)
'ef': 25, # Search width (default: 25)
'use': 'embedding' # Use "data" or "embedding"
})
# Using a vector directly
results = await client.ann({
'vector': [0.1, 0.2, 0.3, ...],
'k': 10
})
# Using get_similar (always available, no license required)
similar = await client.get_similar({
'key': 'user:john',
'k': 10
})
QUERY
Make queries in natural language.
result = await client.query({
'query': 'Insert the value 5 into the grades array of user:123',
'backend': 'openai:gpt-4o-mini' # or "ollama:model-name"
})
SET_MIDDLEWARE
Make the LLM analyze incoming queries and decide if it must reject them, accept them or modify them.
await client.set_middleware({
'operation': 'SET',
'middleware': 'Only accept requests that have the amount field specified'
})
Analytics Operations
GET_OPERATIONS
Returns history of recent database operations.
operations = await client.get_operations({})
GET_ACCESS_FREQUENCY
Returns the number of times an object has been queried.
frequency = await client.get_access_frequency({
'key': 'user:john'
})
# Returns: {"type": "SUCCESS", "message": "OK", "id": "...", "data": 42}
Mindspace Operations
Mindspaces are cognitive contexts for AI-powered conversations and semantic operations.
SET_MINDSPACE / CREATE_MINDSPACE
Creates a new mindspace.
# Create with custom ID
mindspace = await client.set_mindspace({
'mindspace_id': 'conversation-1'
})
# Or use the alias
mindspace = await client.create_mindspace({
'mindspace_id': 'project-alpha'
})
DELETE_MINDSPACE
Deletes a mindspace and all its associated context.
await client.delete_mindspace({
'mindspace_id': 'conversation-1'
})
CHAT_MINDSPACE
Chat with a mindspace using AI. The mindspace maintains conversation context.
response = await client.chat_mindspace({
'mindspace_id': 'conversation-1',
'message': 'What do you know about users?'
})
# Returns: {"response": "AI response text...", "context": [...]}
LECTURE_MINDSPACE
Imports text corpus into a mindspace for semantic search and context retrieval.
await client.lecture_mindspace({
'mindspace_id': 'conversation-1',
'corpus': 'User John Doe is a software engineer who specializes in Rust and distributed systems...'
})
Real-time Notifications
Subscribe to real-time updates when an object changes.
async def on_update(data):
print('User updated!', data)
await client.notify('user:john', on_update)
Schema Class
The Schema class provides an object-oriented way to model your data.
from satori import Satori
from satori.schema import Schema
import asyncio
async def main():
satori = Satori("username", "password", "ws://localhost:1234")
await satori.connect()
# Create a user schema
user = Schema(satori, "user", key="user:john", body={"name": "John", "age": 30})
await user.set()
# Update the user
await user.update("age", 31)
# Get the user
user_data = await user.get()
# Add a friend vertex
await user.set_vertex("user:jane", relation="friend", weight=1.0)
# Get all friends
friends = await user.get_vertex()
# Add tags
await user.push("premium", "tags")
await user.push("active", "tags")
# Find similar users
similar = await user.get_similar(k=5)
# Encrypt the user data
await user.encrypt("my-secret-key")
# Delete the user
await user.delete()
asyncio.run(main())
Schema Methods
set()- Create the objectdelete()- Delete the objectget()- Get object dataupdate(field, value)- Update a fieldencrypt(key)- Encrypt the objectdecrypt(key)- Decrypt the objectset_vertex(vertex, relation, weight)- Add a vertexget_vertex()- Get all verticesdelete_vertex(vertex)- Delete a vertexdfs(relation)- Depth-first searchgraph_bfs(relation)- Breadth-first searchgraph_shortest_path(target)- Find shortest pathpush(value, array)- Add to arraypop(array)- Remove last from arraysplice(array)- Remove first from arrayremove(value, array)- Remove specific valueann(k, ef, use)- Find similar (ANN)get_similar(k, ef, use)- Find similar (alias)
Response Format
All successful responses follow this structure:
{
"type": "SUCCESS", # "SUCCESS" or "ERROR"
"message": "OK", # Status message
"id": "request-id", # Request ID
"key": "optional-key", # Object key (if applicable)
"data": {...} # Response data (if applicable)
}
Error Response
{
"type": "ERROR",
"message": "Error description",
"id": "request-id"
}
AI Response (ask)
{
"type": "SUCCESS",
"message": "SUCCESS",
"id": "request-id",
"data": {
"response": "AI-generated answer...",
"context": [...],
"session": "session-id"
AI }
}
Response (query)
{
"type": "SUCCESS",
"message": "OK",
"id": "request-id",
"data": {
"result": "Operation result...",
"status": "SUCCESS"
}
}
AI Response (ann/get_similar)
{
"type": "SUCCESS",
"message": "OK",
"id": "request-id",
"data": [{"key": "object-key", "distance": 0.123}, ...]
}
Complete Example
import asyncio
from satori import Satori
async def main():
# Initialize client
client = Satori(
username='user',
password='password',
host='ws://localhost:8000'
)
await client.connect()
# Create a user
await client.set({
'key': 'user:john',
'data': {'name': 'John Doe', 'email': 'john@example.com', 'age': 30},
'type': 'user'
})
# Create another user and link them
await client.set({
'key': 'user:jane',
'data': {'name': 'Jane Doe', 'email': 'jane@example.com', 'age': 28},
'type': 'user'
})
# Create a relationship
await client.set_vertex({
'key': 'user:john',
'vertex': {'vertex': 'user:jane', 'relation': 'friend', 'weight': 1.0}
})
# Get all friends of john
friends = await client.get_vertex({'key': 'user:john'})
print(f"John's friends: {friends}")
# Find shortest path from john to jane
path = await client.graph_shortest_path({
'node': 'user:john',
'target': 'user:jane'
})
print(f"Path: {path}")
# Subscribe to updates
async def on_update(data):
print(f'John was updated: {data}')
await client.notify('user:john', on_update)
# Update john
await client.put({
'key': 'user:john',
'replace_field': 'age',
'replace_value': 31
})
asyncio.run(main())
🧠 Key Concepts
- key: Unique identifier of the object
- type: Object type (e.g., 'user', 'post')
- data: Object payload
- vertices: Graph-like relationships between objects
- field_array: Advanced filters for bulk operations
- encryption_key: Key used for AES encryption/decryption
- mindspace: Cognitive context for AI operations
💬 Questions or Suggestions?
Feel free to open an issue or contribute!
With ❤️ from the Satori team.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file satori_client-0.1.9.tar.gz.
File metadata
- Download URL: satori_client-0.1.9.tar.gz
- Upload date:
- Size: 15.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
da7b2a43eacc3cbc6c57bc281253937bc10d206d0a4b3296ef0f90df5d0e814a
|
|
| MD5 |
12879186d4a3b42a3e8f1c51e5384036
|
|
| BLAKE2b-256 |
9adaa246f3d868a5e092726733eb6af31c2afca1b0579bf18defed8f987a89d3
|
File details
Details for the file satori_client-0.1.9-py3-none-any.whl.
File metadata
- Download URL: satori_client-0.1.9-py3-none-any.whl
- Upload date:
- Size: 10.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
15db85eadeaf2694c0830861ce4f3233b1887f67e0ecc8d361aab01e197304fe
|
|
| MD5 |
22dc78f3d967995361e96d08e703c295
|
|
| BLAKE2b-256 |
f4c9d1e8d3ead210f1ed568f5a004ebb1b18ff4142dd73cee6f831a06e678bd2
|