Extend it¶
| Kind | Interface | Built-ins (registry name) |
|---|---|---|
| store | MemoryStore: insert, update, get, delete, query (+ optional vector_search) |
memory, sqlite, pgvector, qdrant |
| embedder | Embedder: embed(texts) |
hashing (offline), ollama (local model), openai, azure_openai, function, agno |
| extractor | Extractor: extract(messages, existing) |
rules (offline), llm, none |
| ranker | Ranker: rank(query, query_embedding, records, limit=, at=) |
hybrid |
| processor | Processor: process(candidate) returns the candidate or None to drop it. A plain function works too. |
drop_secrets (default), redact_pii, min_importance |
| summarizer | Summarizer: summarize(messages, previous) |
extractive, llm |
| adapter | Adapter: matches(target), attach(target, memory, **options), optional detach(target) |
agno, method, callable |
| intelligence | manage(memory, messages, ...) - or replace one part: a router route(memory, turn), a planner plan(memory, query, ...), a scheduler after_turn(memory, report, ...) |
heuristic, llm |
from kioko import Adapter, Embedder, MemoryLayer, MemoryMiddleware, register
@register("embedder", "minilm")
class MiniLM(Embedder):
def __init__(self):
from sentence_transformers import SentenceTransformer
self.model = SentenceTransformer("all-MiniLM-L6-v2")
def embed(self, texts):
return self.model.encode(list(texts)).tolist()
@register("adapter", "my-framework") # tried before the built-in adapters
class MyFrameworkAdapter(Adapter):
def matches(self, target):
return type(target).__module__.startswith("my_framework")
def attach(self, target, memory, **options):
hooks = MemoryMiddleware(memory, **options)
target.before_turn(lambda t: t.add_context(str(hooks.before(t.text, user_id=t.user))))
target.after_turn(lambda t: hooks.after(t.text, t.reply, user_id=t.user))
return target
memory = MemoryLayer.from_config({ # or a path to a JSON file
"store": {"type": "sqlite", "path": "memory.db"},
"embedder": "minilm", # or {"type": "azure_openai", "deployment": "text-embedding-3-small"}
"extractor": {"type": "llm", "llm": {"$import": "my_app.llm:complete"}},
"processors": ["drop_secrets", "redact_pii"],
"dedup_threshold": 0.92,
})
Ship components in their own package so pip install is all it takes. kioko components lists
everything that's available:
[project.entry-points."kioko.embedders"]
minilm = "my_plugin.embedders:MiniLM"
[project.entry-points."kioko.adapters"]
my-framework = "my_plugin.adapter:MyFrameworkAdapter"
A custom store only needs five methods. See examples/04_custom_components.py for a JSON-file store in
about 30 lines, and stores for the reusable contract tests. For a vector database (Azure AI
Search, Elasticsearch, Milvus ...), implement vector_search, as the pgvector and Qdrant stores do.
The extraction rules can be extended without a new extractor:
RuleBasedExtractor(extra_rules=[Rule("ticket", r"^my ticket is (?P<id>[A-Z]+-\d+)$", template="User's open ticket is {id}", key="work.ticket", flags=0)]).