Skip to main content

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

  1. Basic Operations
  2. Crypto Operations
  3. Graph Operations
  4. AI Operations
  5. Analytics Operations
  6. Mindspace Operations
  7. Real-time Notifications
  8. Schema Class
  9. 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 object
  • delete() - Delete the object
  • get() - Get object data
  • update(field, value) - Update a field
  • encrypt(key) - Encrypt the object
  • decrypt(key) - Decrypt the object
  • set_vertex(vertex, relation, weight) - Add a vertex
  • get_vertex() - Get all vertices
  • delete_vertex(vertex) - Delete a vertex
  • dfs(relation) - Depth-first search
  • graph_bfs(relation) - Breadth-first search
  • graph_shortest_path(target) - Find shortest path
  • push(value, array) - Add to array
  • pop(array) - Remove last from array
  • splice(array) - Remove first from array
  • remove(value, array) - Remove specific value
  • ann(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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

satori_client-0.1.9.tar.gz (15.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

satori_client-0.1.9-py3-none-any.whl (10.3 kB view details)

Uploaded Python 3

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

Hashes for satori_client-0.1.9.tar.gz
Algorithm Hash digest
SHA256 da7b2a43eacc3cbc6c57bc281253937bc10d206d0a4b3296ef0f90df5d0e814a
MD5 12879186d4a3b42a3e8f1c51e5384036
BLAKE2b-256 9adaa246f3d868a5e092726733eb6af31c2afca1b0579bf18defed8f987a89d3

See more details on using hashes here.

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

Hashes for satori_client-0.1.9-py3-none-any.whl
Algorithm Hash digest
SHA256 15db85eadeaf2694c0830861ce4f3233b1887f67e0ecc8d361aab01e197304fe
MD5 22dc78f3d967995361e96d08e703c295
BLAKE2b-256 f4c9d1e8d3ead210f1ed568f5a004ebb1b18ff4142dd73cee6f831a06e678bd2

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page