Development
zleap-sag Python engine
Embed DataEngine directly and run the ingest, extract, and search lifecycle.zleap-sag is the maintained Python knowledge engine beneath the SAG application. Its distribution name is zleap-sag, its import path is zleap.sag, it requires Python 3.11+, and it uses the MIT License.
Install
The default local combination uses SQLite and LanceDB and requires no external database:
pip install zleap-sagThe SAG application currently requires zleap-sag>=0.7.1.
Complete lifecycle
import asyncio
from zleap.sag import DataEngine, EngineConfig
from zleap.sag.config import EmbeddingConfig, LLMConfig
async def main() -> None:
config = EngineConfig(
llm=LLMConfig(
api_key="sk-...",
base_url="https://your-openai-compatible-host/v1",
model="qwen3.6-flash",
),
embedding=EmbeddingConfig(model="bge-large-en-v1.5"),
language="en",
)
async with DataEngine(config) as engine:
ingest = await engine.ingest("knowledge.md")
extract = await engine.extract()
result = await engine.search(
"Why is SAG suitable for multi-hop retrieval?",
strategy="multi",
top_k=5,
)
print(ingest.chunk_count, extract.event_count)
for section in result.sections:
print(section.get("content", "")[:200])
asyncio.run(main())One DataEngine instance represents one logical source. Local data is created automatically under ./.zleap/; add that directory to .gitignore.
Configuration methods
Choose one of two approaches:
| Method | Construction | Best for |
|---|---|---|
| Explicit injection | EngineConfig(llm=..., embedding=...) | Libraries, notebooks, and explicit application composition |
| Environment | EngineConfig.from_env() | Containers and 12-factor services |
OPENAI_API_KEY=sk-...
OPENAI_BASE_URL=https://your-openai-compatible-host/v1
LLM_MODEL=qwen3.6-flash
EMBEDDING_MODEL=bge-large-en-v1.5from zleap.sag import EngineConfig
config = EngineConfig.from_env()EngineConfig(...) does not read environment variables implicitly. If Embedding uses a separate endpoint, construct EmbeddingConfig(api_key=..., base_url=..., model=...) explicitly.
DataEngine API
| Method | Purpose |
|---|---|
await engine.start() | Initialize connections and the local schema |
await engine.aclose() | Close resources; async with does this automatically |
await engine.chunk(source) | Parse and chunk a path or raw string without persistence |
await engine.ingest(path, ...) | Chunk, embed, and persist chunks and vectors |
await engine.extract(...) | Extract and save the event-entity index |
await engine.search(...) | Return SearchResult, sections, and statistics |
await engine.init_schema() | Initialize the production schema idempotently |
Typed results live in zleap.sag.results: ChunkResult, IngestResult, ExtractResult, and SearchResult. Every engine exception inherits SagError.
Storage backends
| Deployment | Relational storage | Vector storage | Extra |
|---|---|---|---|
| Local default | SQLite | LanceDB | None |
| Single database | PostgreSQL | pgvector | zleap-sag[postgres] |
| Split production | MySQL/PostgreSQL/OceanBase | Elasticsearch | [mysql], [postgres], [es] |
| OceanBase | OceanBase 4.3.3+ | OceanBase vector | [mysql] |
Changing EngineConfig does not require changes to ingest, extract, or search calls. Connections are currently process-global resources; one process should use one EngineConfig.