Skip to content

Commit

Permalink
Update README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
shihanwan committed Oct 1, 2024
1 parent 8c707ae commit 038d236
Showing 1 changed file with 69 additions and 55 deletions.
124 changes: 69 additions & 55 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
# MemOnto 🧠

`memonto` (memory + ontology) adds memory to AI agents with an emphasis on user defined ontology. Define your own [RDF](https://www.w3.org/RDF/) ontology then have `memonto` automatically extract information that maps onto that ontology.

```
┌─────────────────────────────── ┌──────────────────────┐ ┌───────────────────────────────────┐
Message │ LLM │ │ Memory Graph │
│ │
{Otto von Bismarck was a │ │
Prussian statesman and │ │ │ ...
diplomat who oversaw the │ [Otto von Bismarck] │ │ │
unification of Germany...} ┼──────► │ │ │
│ is a [Person] who │ │ ┌───────────────▼───────────────┐
└─────────────────────────────── │ │ │ Otto von Bismarck
┌─────────────────────────────── │ lives in a [Place] │ │ └────────┬──────┬───────────────┘
Ontology │ │ │ │ │
┼──────► called [Prussia] ┼──────► livesAt│ │partOf
┌─────────────┐ │ │ │ │ │
│ Person │ │ │ and participated in │ ┌────────▼┐┌────▼───────────────┐
└───┬─────┬───┘ │ │ Prussia ││ German Unification │
│ │ │ an [Event] called │ │ └─┬─────┬─┘└──────┬─────┬───────┘
livesAt│ │partOf │ │ │ │ │ │ │ │
│ │ │ [German Unification] │
┌─────────▼─┐ ┌─▼─────────┐ │ │ │ ... ... ... ... │
│ Place │ │ Event │ │ │ │ │
└───────────┘ └───────────┘ │ │
│ │ │ │
└─────────────────────────────── └──────────────────────┘ └───────────────────────────────────┘
`memonto` (_memory + ontology_) adds memory to AI agents based on an user defined ontology. Define your own [RDF](https://www.w3.org/RDF/) ontology with [`rdflib`](https://github.com/RDFLib/rdflib) then have `memonto` automatically extract information that maps onto that ontology into a memory graph. The memories in the memory graph can be queried directly with `SPARQL` queries or contextually summarized.

```
┌─────────────────────────────┐ ┌──────────────────────┐ ┌───────────────────────────────────┐
│ Message │ │ LLM │ │ Memory Graph │
│ │ │ │ │ ...
│ {Otto von Bismarck was a │ │ │ │
│ Prussian statesman and │ │ │ │ ┌───────────────▼───────────────┐
│ diplomat who oversaw the │ │ [Otto von Bismarck] │ │ │ Otto von Bismarck
│ unification of Germany...} ┼──► │ │ └────────┬──────┬───────────────┘
│ │ │ is a [Person] who │ │ │
└─────────────────────────────┘ ┼──► livesAt│ │partOf
┌─────────────────────────────┐ │ lives in a [Place] │ │ │
│ Ontology │ │ │ │ ┌────────▼┐┌────▼───────────────┐
│ ┼──► called [Prussia] │ │ │ Prussia ││ German Unification │
│ ┌─────────────┐ │ │ │ │ └─┬─────┬─┘└──────┬─────┬───────┘
│ │ Person │ │ │ and participated in │ │ │ │ │
│ └───┬─────┬───┘ │ │ ▼ ▼ ▼
│ │ │ │ │ an [Event] called │ │ ... ... ... ...
│ livesAt│ │partOf │ │ │ └─────────────────┬─────────────────┘
│ │ │ │ │ [German Unification] │
│ ┌─────────▼─┐ ┌─▼─────────┐ │ │ │ ┌─────────────────▼─────────────────┐
│ │ Place │ │ Event │ │ │ │ │ │
│ └───────────┘ └───────────┘ │ │ │ │ SPARQL Queries / Memory Summaries
│ │ │ │ │ │
└─────────────────────────────┘ └──────────────────────┘ └───────────────────────────────────┘
```

## 🚀 Install
Expand All @@ -34,13 +34,14 @@ pip install memonto
```

## ⚙️ Configure
**Ephemeral Mode**
### Ephemeral Mode

Use `memonto` all in memory without any data stores.

> [!IMPORTANT]
> When in ephemeral mode, there can be performance issues if the memory data grows too large. This mode is recommended for smaller use cases.
> When in `ephemeral` mode, there can be performance issues if the memory data grows too large. This mode is recommended for smaller use cases.
**Define ontology**
```python
from memonto import Memonto
from rdflib import Graph, Namespace, RDF, RDFS
Expand All @@ -54,23 +55,50 @@ g.bind("hist", HIST)
g.add((HIST.Person, RDF.type, RDFS.Class))
g.add((HIST.Event, RDF.type, RDFS.Class))
g.add((HIST.Place, RDF.type, RDFS.Class))
```

**Configure LLM**
```python
config = {
"model": {
"provider": "openai",
"config": {
"model": "gpt-4o",
"api_key": "api-key",
},
}
}

memonto = Memonto(
ontology=g,
namespaces={"hist": HIST},
ephemeral=True,
)
memonto.configure(config)
```

**With Triple Store**
### Triple Store Mode

A triple store enables the persistent storage of memory data. Currently supports Apache Jena Fuseki as a triple store.

**Install Apache Jena Fuseki**
1. Download Apache Jena Fuseki [here](https://jena.apache.org/download/index.cgi#apache-jena-fuseki).
2. Unzip to desired folder.
```sh
tar -xzf apache-jena-fuseki-X.Y.Z.tar.gz
```
3. Run a local server.
```sh
./fuseki-server --port=8080
```

**Configure Triple Store**
```python
config = {
"triple_store": {
"provider": "apache_jena",
"config": {
"connection_url": "http://localhost:8080/",
"connection_url": "http://localhost:8080/dataset_name",
},
},
"model": {
Expand All @@ -89,7 +117,7 @@ memonto = Memonto(
memonto.configure(config)
```

**With Triple + Vector Stores**
### Triple + Vector Stores Mode

A vector store enables contextual retrieval of memory data, it must be used in conjunction with a triple store. Currently supports Chroma as a vector store.
```python
Expand Down Expand Up @@ -124,7 +152,7 @@ memonto.configure(config)
```

## 🧰 Usage
**RDF Namespaces**
### RDF Namespaces

`memonto` supports RDF namespaces as well. Just pass in a dictionary with the namespace's name along with its `rdflib.Namespace` object.
```python
Expand All @@ -134,7 +162,7 @@ memonto = Memonto(
)
```

**Memory ID**
### Memory ID

For when you want to associate an ontology and memories to an unique `id`.
```python
Expand All @@ -145,19 +173,19 @@ memonto = Memonto(
)
```

**Retain**
### Retain

Extract the relevant information from a message that maps onto your ontology. It will only extract data that matches onto an entity in your ontology.
```python
memonto.retain("Otto von Bismarck was a Prussian statesman who oversaw the unification of Germany.")
```

**Recall**
### Recall

Get a summary of the currently stored memories. You can provide a `context` for `memonto` to only summarize the memories that are relevant to that `context`.

> [!IMPORTANT]
> When in ephemeral mode, all memories will be returned even if a `context` is provided.
> When in `ephemeral` mode, all memories will be returned even if a `context` is provided.
```python
# retrieve summary of memory relevant to a context
memonto.recall("Germany could unify under Prussia or Austria.")
Expand All @@ -166,11 +194,11 @@ memonto.recall("Germany could unify under Prussia or Austria.")
memonto.recall()
```

**Retrieve**
### Retrieve

Get the raw memory data that can be programatically accessed. Instead of a summary, get the actual stored data as a `list[dict]` that can then be manipulated in code.
> [!IMPORTANT]
> When in ephemeral mode, raw queries are not supported.
> When in `ephemeral` mode, raw queries are not supported.
```python
# retrieve raw memory data by schema
memonto.retrieve(uri=HIST.Person)
Expand All @@ -179,14 +207,14 @@ memonto.retrieve(uri=HIST.Person)
memonto.retrieve(query="SELECT ?s ?p ?o WHERE {GRAPH ?g {?s ?p ?o .}}")
```

**Forget**
### Forget

Forget about it.
```python
memonto.forget()
```

**Auto Expand Ontology**
### Auto Expand Ontology

Enable `memonto` to automatically expand your ontology to cover new information. If `memonto` sees new information that **does not** fit onto your ontology, it will automatically add onto your ontology to cover that new information.
```python
Expand All @@ -200,7 +228,7 @@ memonto = Memonto(

## 🔀 Async Usage

All main functionalities have an async version following this function naming pattern: **a{func_name}**
All main functionalities have an async version following this function naming pattern: `def a{func_name}:`
```python
async def main():
await memonto.aretain("Some user query or message")
Expand All @@ -209,20 +237,6 @@ async def main():
await memonto.aforget()
```

## 🔧 Additional Setup

**Apache Jena**
1. Download Apache Jena Fuseki [here](https://jena.apache.org/download/index.cgi#apache-jena-fuseki).
2. Unzip to desired folder.
```sh
tar -xzf apache-jena-fuseki-X.Y.Z.tar.gz
```
3. Run a local server.
```sh
./fuseki-server --port=8080
```


## 🔮 Current and Upcoming

| LLM | | Vector Store | |Triple Store | |
Expand Down

0 comments on commit 038d236

Please sign in to comment.