Sigillum Finansdevelopers
Sigillum.cloud ↗TR
SDK integrations

Python: document assistant example

Instrument an ASGI application and add retrieval, explanation and source observations.

↓
Download example projectSynthetic scenario · source code and setup instructions
ZIP ↗

#1. Install the wheel

Use Python 3.10+ and the service-specific wheel downloaded from the portal.

python -m pip install ./packages/sigillum_finans_sdk-0.11.0-py3-none-any.whl
python -m pip install fastapi uvicorn

HTTPX, OpenTelemetry and cryptography dependencies can be resolved through your institution’s package mirror.

app.py
"""Deterministic document retrieval; no live LLM call."""
import json
import os
from pathlib import Path
from fastapi import FastAPI
from pydantic import BaseModel, Field
from sigillum_finans import start, JsonData, Attachment, References

sdk = start(Path(os.environ["SIGILLUM_CONFIG"]).resolve())
api = FastAPI(title="Sigillum SDK · Document assistant example")
DOCUMENTS = (
    ("D01", "Apply for a card through the mobile application."),
    ("D02", "Update your address from the customer profile screen."),
    ("D03", "Make a transfer from the payments menu."),
)
def data(value):
    return JsonData.raw(json.dumps(value, ensure_ascii=False, separators=(",", ":")))

class Query(BaseModel):
    request_ref: str = Field(min_length=1, max_length=64)
    question: str = Field(min_length=1, max_length=500)

@api.post("/assist")
async def assist(query: Query):
    sdk.set_references(References(session_ref=query.request_ref))
    with sdk.start_step("document-retrieval") as step:
        words = set(query.question.casefold().split())
        ranked = sorted(DOCUMENTS,
            key=lambda item: len(words & set(item[1].casefold().split())), reverse=True)
        chosen = ranked[0]
        step.observe("ai", "retrieval", data({
            "method": "synthetic-keyword-overlap",
            "query": query.question, "documents": [{"id": chosen[0], "text": chosen[1]}]
        }))
    with sdk.start_step("answer-compose") as step:
        result = {"request_ref": query.request_ref, "answer": chosen[1],
                  "source": chosen[0], "demonstration": True}
        step.observe("ai", "explanation", data({
            "method": "document-quotation", "source": chosen[0],
            "message": "Selected the example document with the highest word overlap."
        }))
        step.observe("custom", "assistant.result", data(result))
        original = json.dumps(result, ensure_ascii=False).encode("utf-8")
        step.observe("source", "comparison.source", data({"reference": query.request_ref}),
            attachments=(Attachment("result", original, "application/json",
                                    "comparison.originalContent"),))
    return result

@api.get("/sdk-status")
def status():
    return {"ready": sdk.status.state == "ready", "pending_records": sdk.status.pending_records,
            "lost": sdk.status.lost}

app = sdk.wrap_asgi(api)

Use the configuration supplied by your institution’s portal.

#2. Wrap the ASGI application

Create a single SDK with start(Path(...).resolve()). After defining the routes, use app = sdk.wrap_asgi(api). The SDK observes standard ASGI HTTP messages and in-scope HTTPX calls. WebSockets, arbitrary sockets and every Python library are not automatically instrumented.

#3. Record the document-assistant workflow

The POST /assist example accepts a question, selects from three synthetic local documents by word matching and produces a deterministic answer. It does not call a real LLM. Retrieval source content, explanation, business result and original source attachment are recorded explicitly. Other AI categories are demonstrated separately in the AI observation examples.

#4. Supply JSON, attachments and references

JsonData.raw accepts a valid JSON object as str or immutable bytes. Attachment carries original content. References and ExternalReference add person, session and business references. Avoid parsing and serialising large JSON numbers solely for observation.

#5. Integrate an actual model call

sdk.call_ai and call_ai_async execute the actual operation once. If the return value is not raw JSON, an output= selector supplies the original JSON representation. Do not pre-consume a stream for capture; observe it during normal consumption.

#6. Run the project

Follow the ZIP README and set SIGILLUM_CONFIG to the absolute service-configuration path. Start with uvicorn app:app --host 127.0.0.1 --port 5110. Set POST /assist as the entry point. A /sdk-status response is not evidence of transaction observation: send an actual /assist request.

Sigillum Finans · Source-matched product reference

Search documentation

Search titles and content by entering a topic.

↑ ↓ select · Enter open · Esc closeBrowser-local search